<commit_before>  var epsg4326;
  var markers;
  var marker;
  var center;
  var zoom = 2;
  var pointFeature;
  var point;
  var vectorLayer;
  var gsat;
  var gphy;
  var gmap;
  var ghyb;
  var mapnik;
  var style_blue;
  var map;
OpenLayers.ImgPath = "/images/ol_theme_dark/";
function initMap(mapId)
{
  epsg4326 = new OpenLayers.Projection("EPSG:4326");
  options = {
//     restrictedExtent: extent,
    controls: [
      new OpenLayers.Control.Navigation(),
      new OpenLayers.Control.PanZoomBar(),
      new OpenLayers.Control.LayerSwitcher(),
      new OpenLayers.Control.ScaleLine()
    ],
    numZoomLevels: 20,
    displayProjection: new OpenLayers.Projection("EPSG:4326"),
    maxExtent: new OpenLayers.Bounds(-180,-90, 180, 90),
    maxResolution: 0.3515625,
    units: "m",
    theme: '/openlayers/theme/default/style.css'
  };
  style_blue = OpenLayers.Util.extend({}, OpenLayers.Feature.Vector.style['default']);
  style_blue.strokeColor = "blue";
  style_blue.fillColor = "blue";
// OpenLayers.Layer.XYZ.

   map = new OpenLayers.Map(mapId, options);

  mapnik = new OpenLayers.Layer.OSM();
  mapnik.addOptions({wrapDateLine:true});
  map.addLayer(mapnik);

  // the SATELLITE layer has all 22 zoom level, so we add it first to
    // become the internal base layer that determines the zoom levels of the
    // map.
    gsat = new OpenLayers.Layer.Google(
        "Google Satellite",
        {sphericalMercator: true,type: google.maps.MapTypeId.SATELLITE, numZoomLevels: 22}
    );
    gphy = new OpenLayers.Layer.Google(
        "Google Physical",
        {sphericalMercator: true,type: google.maps.MapTypeId.TERRAIN, visibility: false}
    );
    gmap = new OpenLayers.Layer.Google(
        "Google Streets", // the default
        {sphericalMercator: true,numZoomLevels: 20, visibility: false}
    );
    ghyb = new OpenLayers.Layer.Google(
        "Google Hybrid",
        {sphericalMercator: true,type: google.maps.MapTypeId.HYBRID, numZoomLevels: 22, visibility: false}
    );
    vectorLayer = new OpenLayers.Layer.Vector("Simple Geometry", { displayInLayerSwitcher: false, projection: new OpenLayers.Projection("EPSG:4326")});
    map.addLayers([gsat, gphy, gmap, ghyb,vectorLayer]);

  markers = new OpenLayers.Layer.Markers("Markers", {
    displayInLayerSwitcher: false,
    units: "m",
    projection: "EPSG:900913"
   });
  map.addLayer(markers);

  map.zoomToMaxExtent();
  map.events.on({
    "changebaselayer": function(e) {
        if(e.object.baseLayer.name != "OpenStreetMap")
          $.get('/robots.txt?use_gmap');
      }

  });
}

function setZoom(e)
{
  if(pointFeature)
  {
    drawAccuracy()
  }
}

function getAccuracySize(z)
{
  if(! z)
    zoom = map.getZoom();
  else
    zoom = z;
  resolution = map.getResolutionForZoom(zoom);
  return $('#gtu_lat_long_accuracy').val() / resolution;
}

function drawAccuracy()
{
  if(marker)
  {
    vectorLayer.removeAllFeatures();
    point = new OpenLayers.Geometry.Point(marker.lonlat.lon, marker.lonlat.lat);
    style_blue.pointRadius = getAccuracySize();
    pointFeature = new OpenLayers.Feature.Vector(point, null, style_blue);
    vectorLayer.addFeatures([pointFeature]);
    vectorLayer.redraw();
  }
}

function drawLatLong()
{
  if (marker) {
    removeMarkerFromMap(marker);
  }
  lonlat = new OpenLayers.LonLat($('#gtu_longitude').val(), $('#gtu_latitude').val())
  marker = addMarkerToMap(lonlat, null);
  drawAccuracy();
}

function fetchElevation(lonlat)
{
  ////GOOGLE ELE
  glatlng = new google.maps.LatLng(lonlat.lat,lonlat.lon);
  elevator = new google.maps.ElevationService();
  positionalRequest = {'locations': [glatlng] };
  elevator.getElevationForLocations(positionalRequest, function(results, status)
  {
    if (status == google.maps.ElevationStatus.OK && results[0])
    {
      $('#gtu_elevation').val(results[0].elevation.toFixed(3));
    }
  });
}

function fetchPositions(lonlat, zoom)
{
  $.ajax({
  url: 'http://nominatim.openstreetmap.org/reverse',
  dataType: 'json',
  data: { lat: lonlat.lat, lon: lonlat.lon, zoom: zoom, addressdetails:1, format: 'json'  },
  success: function(data) {
    console.log(data);
  }
});

}

function setPoint( e )
{
  lonlat = getEventPosition(e).wrapDateLine();
  $('#gtu_latitude').val(lonlat.lat);
  $('#gtu_longitude').val(lonlat.lon);
  fetchElevation(lonlat);
  fetchPositions(lonlat,map.getZoom());
  //// GOOGLE ELE
  drawLatLong();
  drawAccuracy();
}

function addMarkerToMap(position, icon)
{
  var marker = new OpenLayers.Marker(position.clone().transform(epsg4326, map.getProjectionObject()), icon);
  markers.addMarker(marker);

            // create a point feature

  drawAccuracy();
  return marker;
}

function removeMarkerFromMap(marker)
{
   markers.removeMarker(marker);
}

function getEventPosition(event)
{
  return map.getLonLatFromViewPortPx(event.xy).clone().transform(map.getProjectionObject(), epsg4326);
}

function setMapCenter(center, zoom)
{
  zoom = parseInt(zoom);
  var numzoom = map.getNumZoomLevels();
  if (zoom >= numzoom) zoom = numzoom - 1;
  map.setCenter(center.clone().transform(epsg4326, map.getProjectionObject()), zoom);
}

  <commit_msg>Disable data fetch for now<commit_after>  var epsg4326;
  var markers;
  var marker;
  var center;
  var zoom = 2;
  var pointFeature;
  var point;
  var vectorLayer;
  var gsat;
  var gphy;
  var gmap;
  var ghyb;
  var mapnik;
  var style_blue;
  var map;
OpenLayers.ImgPath = "/images/ol_theme_dark/";
function initMap(mapId)
{
  epsg4326 = new OpenLayers.Projection("EPSG:4326");
  options = {
//     restrictedExtent: extent,
    controls: [
      new OpenLayers.Control.Navigation(),
      new OpenLayers.Control.PanZoomBar(),
      new OpenLayers.Control.LayerSwitcher(),
      new OpenLayers.Control.ScaleLine()
    ],
    numZoomLevels: 20,
    displayProjection: new OpenLayers.Projection("EPSG:4326"),
    maxExtent: new OpenLayers.Bounds(-180,-90, 180, 90),
    maxResolution: 0.3515625,
    units: "m",
    theme: '/openlayers/theme/default/style.css'
  };
  style_blue = OpenLayers.Util.extend({}, OpenLayers.Feature.Vector.style['default']);
  style_blue.strokeColor = "blue";
  style_blue.fillColor = "blue";
// OpenLayers.Layer.XYZ.

   map = new OpenLayers.Map(mapId, options);

  mapnik = new OpenLayers.Layer.OSM();
  mapnik.addOptions({wrapDateLine:true});
  map.addLayer(mapnik);

  // the SATELLITE layer has all 22 zoom level, so we add it first to
    // become the internal base layer that determines the zoom levels of the
    // map.
    gsat = new OpenLayers.Layer.Google(
        "Google Satellite",
        {sphericalMercator: true,type: google.maps.MapTypeId.SATELLITE, numZoomLevels: 22}
    );
    gphy = new OpenLayers.Layer.Google(
        "Google Physical",
        {sphericalMercator: true,type: google.maps.MapTypeId.TERRAIN, visibility: false}
    );
    gmap = new OpenLayers.Layer.Google(
        "Google Streets", // the default
        {sphericalMercator: true,numZoomLevels: 20, visibility: false}
    );
    ghyb = new OpenLayers.Layer.Google(
        "Google Hybrid",
        {sphericalMercator: true,type: google.maps.MapTypeId.HYBRID, numZoomLevels: 22, visibility: false}
    );
    vectorLayer = new OpenLayers.Layer.Vector("Simple Geometry", { displayInLayerSwitcher: false, projection: new OpenLayers.Projection("EPSG:4326")});
    map.addLayers([gsat, gphy, gmap, ghyb,vectorLayer]);

  markers = new OpenLayers.Layer.Markers("Markers", {
    displayInLayerSwitcher: false,
    units: "m",
    projection: "EPSG:900913"
   });
  map.addLayer(markers);

  map.zoomToMaxExtent();
  map.events.on({
    "changebaselayer": function(e) {
        if(e.object.baseLayer.name != "OpenStreetMap")
          $.get('/robots.txt?use_gmap');
      }

  });
}

function setZoom(e)
{
  if(pointFeature)
  {
    drawAccuracy()
  }
}

function getAccuracySize(z)
{
  if(! z)
    zoom = map.getZoom();
  else
    zoom = z;
  resolution = map.getResolutionForZoom(zoom);
  return $('#gtu_lat_long_accuracy').val() / resolution;
}

function drawAccuracy()
{
  if(marker)
  {
    vectorLayer.removeAllFeatures();
    point = new OpenLayers.Geometry.Point(marker.lonlat.lon, marker.lonlat.lat);
    style_blue.pointRadius = getAccuracySize();
    pointFeature = new OpenLayers.Feature.Vector(point, null, style_blue);
    vectorLayer.addFeatures([pointFeature]);
    vectorLayer.redraw();
  }
}

function drawLatLong()
{
  if (marker) {
    removeMarkerFromMap(marker);
  }
  lonlat = new OpenLayers.LonLat($('#gtu_longitude').val(), $('#gtu_latitude').val())
  marker = addMarkerToMap(lonlat, null);
  drawAccuracy();
}

function fetchElevation(lonlat)
{
  ////GOOGLE ELE
  glatlng = new google.maps.LatLng(lonlat.lat,lonlat.lon);
  elevator = new google.maps.ElevationService();
  positionalRequest = {'locations': [glatlng] };
  elevator.getElevationForLocations(positionalRequest, function(results, status)
  {
    if (status == google.maps.ElevationStatus.OK && results[0])
    {
      $('#gtu_elevation').val(results[0].elevation.toFixed(3));
    }
  });
}

function fetchPositions(lonlat, zoom)
{
  $.ajax({
  url: 'http://nominatim.openstreetmap.org/reverse',
  dataType: 'json',
  data: { lat: lonlat.lat, lon: lonlat.lon, zoom: zoom, addressdetails:1, format: 'json'  },
  success: function(data) {
    console.log(data);
  }
});

}

function setPoint( e )
{
  lonlat = getEventPosition(e).wrapDateLine();
  $('#gtu_latitude').val(lonlat.lat);
  $('#gtu_longitude').val(lonlat.lon);
  fetchElevation(lonlat);
  //fetchPositions(lonlat,map.getZoom());
  //// GOOGLE ELE
  drawLatLong();
  drawAccuracy();
}

function addMarkerToMap(position, icon)
{
  var marker = new OpenLayers.Marker(position.clone().transform(epsg4326, map.getProjectionObject()), icon);
  markers.addMarker(marker);

            // create a point feature

  drawAccuracy();
  return marker;
}

function removeMarkerFromMap(marker)
{
   markers.removeMarker(marker);
}

function getEventPosition(event)
{
  return map.getLonLatFromViewPortPx(event.xy).clone().transform(map.getProjectionObject(), epsg4326);
}

function setMapCenter(center, zoom)
{
  zoom = parseInt(zoom);
  var numzoom = map.getNumZoomLevels();
  if (zoom >= numzoom) zoom = numzoom - 1;
  map.setCenter(center.clone().transform(epsg4326, map.getProjectionObject()), zoom);
}

  <|endoftext|>


<commit_before>/*
---
script: utils.js
description: utility functions
license: MIT-style license
authors:
- Mark Obcena
provides: [typeOf, instanceOf, checkArg]
...
*/

(function(){

exports.typeOf = function(item){
	var type = Object.prototype.toString.call(item);
	return type.replace(/\[object\s(.*)\]/, '$1').toLowerCase();
};

exports.instanceOf = function(item, type){
	var realtype = typeof item;
	switch(realtype){
		case 'string': item = new String(item); break;
		case 'number': item = new Number(item); break;
		case 'boolean': item = new Boolean(item); break;
	}
	return item instanceof type;
};

exports.checkArg = function(arg, fn){
	if (fn.length === 0) return false;
	var fnString = (fn.toSource) ? fn.toSource() : fn.toString();
	return new RegExp('^[\s(]*function[^(]*\\(' + arg + '[,\\)]+').test(fnString);
};

})();<commit_msg>* Added extend utility<commit_after>/*
---
script: utils.js
description: utility functions
license: MIT-style license
authors:
- Mark Obcena
provides: [typeOf, instanceOf, checkArg]
...
*/

(function(){

exports.typeOf = function(item){
	var type = Object.prototype.toString.call(item);
	return type.replace(/\[object\s(.*)\]/, '$1').toLowerCase();
};

exports.instanceOf = function(item, type){
	var realtype = typeof item;
	switch(realtype){
		case 'string': item = new String(item); break;
		case 'number': item = new Number(item); break;
		case 'boolean': item = new Boolean(item); break;
	}
	return item instanceof type;
};

exports.checkArg = function(arg, fn){
	if (fn.length === 0) return false;
	var fnString = (fn.toSource) ? fn.toSource() : fn.toString();
	return new RegExp('^[\s(]*function[^(]*\\(' + arg + '[,\\)]+').test(fnString);
};

exports.extend = function(a, b){
	for (var i in b) a[i] = b[i];
	return a;
};

})();
<|endoftext|>


<commit_before>
var buffer        = require('buffer')
var connect       = require('connect')
var Cookies       = require('cookies')
var dispatch      = require('dispatch')
var _             = require('underscore')
var Middlewares   = require('middlewares')

var Service       = require('./Service.js')
var Http          = require('./HttpCode.js')
var RequestFilter = require('./RequestFilter.js')

function ServiceRouter(options, seneca, plugin, passport) {

  this._plugin = plugin
  this._seneca = seneca
  this._options = options
  this._passport = passport
  this._services = {}

  this._passportInitialize = passport.initialize()

  this._buildDispatcher()

  var contentFolder = require('path').normalize(__dirname + '/../web')
  this._staticRequestHandler = connect.static(contentFolder)

  var self = this;

  seneca.add({ role: plugin, cmd: 'register_service' },   cmd_register_service)

  function cmd_register_service(args, callback) {
    seneca.log.info('registering auth service ['+args.service+']')
    passport.use(args.service, args.plugin)
    self.registerService(args.service, args.conf)
    callback()
  }

}

ServiceRouter.prototype.registerService = function(service, conf) {
  this._services[service] = new Service(service, conf)
}

ServiceRouter.prototype._getServiceName = function(req) {
  return req.param('service') || 'local'
}

ServiceRouter.prototype._getService = function(req) {
  var serviceName = this._getServiceName(req)
  var service = this._services[serviceName]
  if(!service) {
    this._seneca.log.error('no service with name ['+serviceName+']')
  }
  return this._services[this._getServiceName(req)]
}

ServiceRouter.prototype._authRequest = function(req, res, next) {
  var prefix = req.query && req.query.prefix
  var context = req.query && req.query.context

  var self = this

  var serviceName = self._getServiceName(req)

  if( prefix ) {
    res.seneca.cookies.set(self._options.transientPrefix + 'url-prefix', prefix)
  }

  if( context ) {
    res.seneca.cookies.set(self._options.transientPrefix + 'context', context)
  }
  // TODO: The local auth plugin should not be treated differently than other plugins

  if(serviceName !== 'local') {
    var func
    if (!self._options.action || self._options.action == 'login') {
      func = function (err, user, info) {

        if(err) {
          return next(err)
        }
        self._seneca.act(_.extend({}, user, {role: 'auth', trigger: 'service-login', service: self._getServiceName(req)}),
          function (err, user) {
            if (err) return self._afterLogin(err, next, req, res)

            self._seneca.act({role: 'user', cmd: 'login', nick: user.nick, auto: true}, function (err, out) {
              req.user = out
              self._afterLogin(err, next, req, res)
            })
          }
        )
      }
    } else {
      func = function (err, data, info) {

        if(err) {
          return next(err)
        }
        self._seneca.act({role: 'auth', trigger: 'service-' + self._options.action, service: self._getServiceName(req),
            context: req.seneca.cookies.get(self._options.transientPrefix + 'context'),
            data: data
          },

          // FIX: should call afterLogin and use options for redirect

          function (err, redirect) {
            if (err) return next(err)
            //res.redirect(redirect)
            sendredirect(Http.FOUND, res, redirect)
          }
        )
      }
    }
  }

  self._passport.authenticate(serviceName, self._getService(req).conf().authconf, func)(req, res, next)
}

ServiceRouter.prototype._templatize = function(val) {
  return ':'+val
}

ServiceRouter.prototype._buildDispatcher = function() {

  var self = this;

  var routes = {}
  routes[this._options.urlpath.login]    = {
    GET: function(req, res, next) {
      self._authRequest(req, res, function(err) {
        self._afterLogin(err, next, req, res)
      })
    },
    POST: function(req, res, next) {
      req.query = _.extend({}, req.query||{}, req.body||{})

      // TODO: make general
      if( !req.query.username ) {
        req.query.username = null != req.query.nick ? req.query.nick : req.query.email
      }

      self._authRequest(req, res, function(err) {
        self._afterLogin(err, next, req, res)
      })
    },
  }
  routes[this._options.urlpath.logout] = function (req, res, next) {
    var clientToken = req.seneca.cookies.get(self._options.tokenkey)
    var serverToken
    res.seneca.cookies.set(self._options.tokenkey)

    if( req.seneca ) {
      serverToken = req.seneca.login && req.seneca.login.token
      delete req.seneca.user
      delete req.seneca.login
    }

    if( clientToken ) {
      self._seneca.act({role: 'user', cmd: 'logout', token: clientToken}, self._logerr)
    }

    if( serverToken && serverToken != clientToken ) {
      self._seneca.log('auth', 'token-mismatch', clientToken, serverToken)
      self._seneca.act({role: 'user', cmd: 'logout', token: serverToken}, self._logerr)
    }

    try { req.logout() } catch(err) { self._logerr(err) }

    var redirect = self._redirection(req, res, 'logout')

    self._respond(null, res, redirect.win, {ok: true})
  }

  routes[self._options.prefix + '/' + self._templatize('service')] = function (req, res, next, service) {
    if(!req.params) {
      req.params = {}
    }
    req.params.service = service

    if(service !== self._options.urlpath.instance &&
      service !== self._options.urlpath.register &&
      service !== self._options.urlpath.reset_create &&
      service !== self._options.urlpath.reset_load &&
      service !== self._options.urlpath.reset_execute) {
      self._authRequest(req, res, function (err) {
        if (err) {
          return next(err)
        }
      })

    } else {
      next()
    }
  }

  routes[self._options.prefix + '/' + self._templatize('service') + '/callback'] = function (req, res, next, service) {

    if(!req.params) {
      req.params = {}
    }
    req.params.service = service

    self._authRequest(req, res, function (err) {
      if (err) {
        next(err)
      } else {
        self._afterLogin(undefined, next, req, res)
      }
    })
  }
  this._dispatcher = dispatch(routes)
}

ServiceRouter.prototype.middleware = function() {

  var self = this

  var authMiddlewares = new Middlewares()
  authMiddlewares.use(this._passportInitialize, this)
  authMiddlewares.use(require('./middleware/senecaSession.js'))
  authMiddlewares.use(require('./middleware/restrictAuthOnly.js'))
  authMiddlewares.use(this._dispatcher, this)

  var preparationMiddlewares = new Middlewares()
  preparationMiddlewares.use(require('./middleware/static.js')(this._options))
  preparationMiddlewares.use(require('./middleware/cookies.js')())
  preparationMiddlewares.use(require('./middleware/filter.js')(this._options, authMiddlewares))

}

ServiceRouter.prototype.forwardRequestToService = function () {
  var self = this
  return function ( req, res, args, act, respond ) {

    var redirect = self._redirection(req, res, args.cmd)

    var user = req.seneca && req.seneca.user
    if( user ) {
      args.user = user
    }

    var login = req.seneca && req.seneca.login
    if( login ) {
      args.login = login
    }

    act(args, function( err, out ) {

      if( err ) {
        err.seneca = err.seneca || {}
        err.seneca.httpredirect = redirect && redirect.fail
        return respond(err)
      }

      out.httpstatus$ = out.ok ? Http.OK : Http.BAD_REQUEST
      out.httpredirect$ = redirect && redirect.win
      respond(null, out)
    })
  }
}

ServiceRouter.prototype._redirection = function(req, res, kind) {
  var transientPrefix = req.seneca.cookies.get(this._options.transientPrefix + 'url-prefix')
  req.seneca.cookies.set(this._options.transientPrefix + 'url-prefix')

  transientPrefix = (req.query && req.query.prefix) ? req.query.prefix : transientPrefix || ''

  var redirect = false
  var ct = (req.headers['content-type']||'').split(';')[0]

  if( this._options.redirect.always ) {
    redirect = true
  } else if( !_.isUndefined(req.query.redirect) ) {
    redirect = S(req.query.redirect).toBoolean()
  } else if( 'application/x-www-form-urlencoded' == ct || 'multipart/form-data' == ct ) {
    redirect = true
  } else if( 'application/json' == ct ) {
    redirect = false
  } else {
    redirect = true
  }

  if( redirect ) {
    var rk = this._options.redirect[kind]

    redirect = {
      win:  _.isString(req.query.win) ? req.query.win : transientPrefix + ( (rk && rk.win)  || this._options.redirect.win ),
      fail: _.isString(req.query.fail) ? req.query.fail : transientPrefix + ( (rk && rk.fail) || this._options.redirect.fail ),
    }
  }

  return redirect
}

ServiceRouter.prototype._logerr = function(err) {
  if( err ) {
    return this._seneca.log('error', err)
  }
}

ServiceRouter.prototype._afterLogin = function(err, next, req, res) {
  if( err && !err.why ) return next(err)
  var self = this

  var context = req.seneca.cookies.get(this._options.transientprefix + 'context')
  res.seneca.cookies.set(this._options.transientprefix + 'context')

  var redirect = this._redirection(req, res, 'login')

  // req.user actually == {ok: , user: , login: }
  if( req.user && req.user.ok ) {
    // rename passport req.user prop
    req.seneca.user = req.user.user
    req.seneca.login = req.user.login

    this._adminLocal(req, req.seneca.user)

    res.seneca.cookies.set(this._options.tokenkey, req.seneca.login.token)

    if( '' != context ) {
      req.seneca.login.context = context
      req.seneca.login.save$(function(err) {
        self._do_respond(req, res, redirect, err)
      })
    } else {
      self._do_respond(req, res, redirect, undefined)
    }
  } else {
    //var out = {ok: false, why: (req.user&&req.user.why)||'no-user'}
    //delete req.user
    var out = {ok: false, why: err.why}
    if( redirect ) {
      req.seneca.log.debug('redirect', 'login', 'fail', redirect.fail)

      sendredirect( Http.FOUND, res, redirect.fail )
    } else {
      sendjson(Http.BAD_REQUEST, res, out)
    }
  }

}

ServiceRouter.prototype._do_respond = function(req, res, redirect, err) {
  if( err) return next(err)

  if( redirect ) {
    req.seneca.log.debug('redirect', 'login', 'win', redirect.win)
    sendredirect( Http.FOUND, res, redirect.win )
  } else {
    // FIX: this should call instance
    // FIX: how to handle errors here?
    this._seneca.act({role: this._plugin, cmd: 'clean', user: req.seneca.user, login: req.seneca.login}, function(err, out) {

      out.ok = true

      // FIX: should be provided by seneca-web
      sendjson( Http.OK, res, out )
    })
  }
}

ServiceRouter.prototype._respond = function(err, res, redirect, data) {

  if( redirect ) {
    //res.redirect( redirect )
    sendredirect(Http.FOUND, res, redirect)
  } else {
    var httpCode = Http.OK
    if(_.isNumber(err)) {
      httpCode = err
    } else if(_.isObject(err)) {
      httpCode = Http.INTERNAL_SERVER_ERROR
    } else if(!data.ok) {
      httpCode = Http.BAD_REQUEST
    }
    sendjson(httpCode, res, data)
  }
}

// TODO: move to seneca-web
function sendredirect(code, res, url) {
  res.writeHead(Http.MOVED_PERMANENTLY, {Location: url})
  res.end()
}

// TODO: move to seneca-web
function sendjson( code, res, out ) {
  // TODO: need killcircles
  var outjson = JSON.stringify(out)
  res.writeHead( code, {
    'Content-Type':   'application/json',
    'Cache-Control':  'private, max-age=0, no-cache, no-store',
    'Content-Length': buffer.Buffer.byteLength(outjson)
  })
  res.end( outjson )
}

module.exports = ServiceRouter
<commit_msg>minor<commit_after>
var buffer        = require('buffer')
var connect       = require('connect')
var Cookies       = require('cookies')
var dispatch      = require('dispatch')
var _             = require('underscore')
var Middlewares   = require('middlewares')

var Service       = require('./Service.js')
var Http          = require('./HttpCode.js')
var RequestFilter = require('./RequestFilter.js')

function ServiceRouter(options, seneca, plugin, passport) {

  this._plugin = plugin
  this._seneca = seneca
  this._options = options
  this._passport = passport
  this._services = {}

  this._passportInitialize = passport.initialize()

  this._buildDispatcher()

  var contentFolder = require('path').normalize(__dirname + '/../web')
  this._staticRequestHandler = connect.static(contentFolder)

  var self = this;

  seneca.add({ role: plugin, cmd: 'register_service' },   cmd_register_service)

  function cmd_register_service(args, callback) {
    seneca.log.info('registering auth service ['+args.service+']')
    passport.use(args.service, args.plugin)
    self.registerService(args.service, args.conf)
    callback()
  }

}

ServiceRouter.prototype.registerService = function(service, conf) {
  this._services[service] = new Service(service, conf)
}

ServiceRouter.prototype._getServiceName = function(req) {
  return req.param('service') || 'local'
}

ServiceRouter.prototype._getService = function(req) {
  var serviceName = this._getServiceName(req)
  var service = this._services[serviceName]
  if(!service) {
    this._seneca.log.error('no service with name ['+serviceName+']')
  }
  return this._services[this._getServiceName(req)]
}

ServiceRouter.prototype._authRequest = function(req, res, next) {
  var prefix = req.query && req.query.prefix
  var context = req.query && req.query.context

  var self = this

  var serviceName = self._getServiceName(req)

  if( prefix ) {
    res.seneca.cookies.set(self._options.transientPrefix + 'url-prefix', prefix)
  }

  if( context ) {
    res.seneca.cookies.set(self._options.transientPrefix + 'context', context)
  }
  // TODO: The local auth plugin should not be treated differently than other plugins

  if(serviceName !== 'local') {
    var func
    if (!self._options.action || self._options.action == 'login') {
      func = function (err, user, info) {

        if(err) {
          return next(err)
        }
        self._seneca.act(_.extend({}, user, {role: 'auth', trigger: 'service-login', service: self._getServiceName(req)}),
          function (err, user) {
            if (err) return self._afterLogin(err, next, req, res)

            self._seneca.act({role: 'user', cmd: 'login', nick: user.nick, auto: true}, function (err, out) {
              req.user = out
              self._afterLogin(err, next, req, res)
            })
          }
        )
      }
    } else {
      func = function (err, data, info) {

        if(err) {
          return next(err)
        }
        self._seneca.act({role: 'auth', trigger: 'service-' + self._options.action, service: self._getServiceName(req),
            context: req.seneca.cookies.get(self._options.transientPrefix + 'context'),
            data: data
          },

          // FIX: should call afterLogin and use options for redirect

          function (err, redirect) {
            if (err) return next(err)
            //res.redirect(redirect)
            sendredirect(Http.FOUND, res, redirect)
          }
        )
      }
    }
  }

  self._passport.authenticate(serviceName, self._getService(req).conf().authconf, func)(req, res, next)
}

ServiceRouter.prototype._templatize = function(val) {
  return ':'+val
}

ServiceRouter.prototype._buildDispatcher = function() {

  var self = this;

  var routes = {}
  routes[this._options.urlpath.login]    = {
    GET: function(req, res, next) {
      self._authRequest(req, res, function(err) {
        self._afterLogin(err, next, req, res)
      })
    },
    POST: function(req, res, next) {
      req.query = _.extend({}, req.query||{}, req.body||{})

      // TODO: make general
      if( !req.query.username ) {
        req.query.username = null != req.query.nick ? req.query.nick : req.query.email
      }

      self._authRequest(req, res, function(err) {
        self._afterLogin(err, next, req, res)
      })
    },
  }
  routes[this._options.urlpath.logout] = function (req, res, next) {
    var clientToken = req.seneca.cookies.get(self._options.tokenkey)
    var serverToken
    res.seneca.cookies.set(self._options.tokenkey)

    if( req.seneca ) {
      serverToken = req.seneca.login && req.seneca.login.token
      delete req.seneca.user
      delete req.seneca.login
    }

    if( clientToken ) {
      self._seneca.act({role: 'user', cmd: 'logout', token: clientToken}, self._logerr)
    }

    if( serverToken && serverToken != clientToken ) {
      self._seneca.log('auth', 'token-mismatch', clientToken, serverToken)
      self._seneca.act({role: 'user', cmd: 'logout', token: serverToken}, self._logerr)
    }

    try { req.logout() } catch(err) { self._logerr(err) }

    var redirect = self._redirection(req, res, 'logout')

    self._respond(null, res, redirect.win, {ok: true})
  }

  routes[self._options.prefix + '/' + self._templatize('service')] = function (req, res, next, service) {
    if(!req.params) {
      req.params = {}
    }
    req.params.service = service

    if(service !== self._options.urlpath.instance &&
      service !== self._options.urlpath.register &&
      service !== self._options.urlpath.reset_create &&
      service !== self._options.urlpath.reset_load &&
      service !== self._options.urlpath.reset_execute) {
      self._authRequest(req, res, function (err) {
        if (err) {
          return next(err)
        }
      })

    } else {
      next()
    }
  }

  routes[self._options.prefix + '/' + self._templatize('service') + '/callback'] = function (req, res, next, service) {

    if(!req.params) {
      req.params = {}
    }
    req.params.service = service

    self._authRequest(req, res, function (err) {
      if (err) {
        next(err)
      } else {
        self._afterLogin(undefined, next, req, res)
      }
    })
  }
  this._dispatcher = dispatch(routes)
}

ServiceRouter.prototype.middleware = function() {

  var authMiddlewares = new Middlewares()
  authMiddlewares.use(this._passportInitialize, this)
  authMiddlewares.use(require('./middleware/senecaSession.js'))
  authMiddlewares.use(require('./middleware/restrictAuthOnly.js'))
  authMiddlewares.use(this._dispatcher, this)

  var preparationMiddlewares = new Middlewares()
  preparationMiddlewares.use(require('./middleware/static.js')(this._options))
  preparationMiddlewares.use(require('./middleware/cookies.js')())
  preparationMiddlewares.use(require('./middleware/filter.js')(this._options, authMiddlewares))

}

ServiceRouter.prototype.forwardRequestToService = function () {
  var self = this
  return function ( req, res, args, act, respond ) {

    var redirect = self._redirection(req, res, args.cmd)

    var user = req.seneca && req.seneca.user
    if( user ) {
      args.user = user
    }

    var login = req.seneca && req.seneca.login
    if( login ) {
      args.login = login
    }

    act(args, function( err, out ) {

      if( err ) {
        err.seneca = err.seneca || {}
        err.seneca.httpredirect = redirect && redirect.fail
        return respond(err)
      }

      out.httpstatus$ = out.ok ? Http.OK : Http.BAD_REQUEST
      out.httpredirect$ = redirect && redirect.win
      respond(null, out)
    })
  }
}

ServiceRouter.prototype._redirection = function(req, res, kind) {
  var transientPrefix = req.seneca.cookies.get(this._options.transientPrefix + 'url-prefix')
  req.seneca.cookies.set(this._options.transientPrefix + 'url-prefix')

  transientPrefix = (req.query && req.query.prefix) ? req.query.prefix : transientPrefix || ''

  var redirect = false
  var ct = (req.headers['content-type']||'').split(';')[0]

  if( this._options.redirect.always ) {
    redirect = true
  } else if( !_.isUndefined(req.query.redirect) ) {
    redirect = S(req.query.redirect).toBoolean()
  } else if( 'application/x-www-form-urlencoded' == ct || 'multipart/form-data' == ct ) {
    redirect = true
  } else if( 'application/json' == ct ) {
    redirect = false
  } else {
    redirect = true
  }

  if( redirect ) {
    var rk = this._options.redirect[kind]

    redirect = {
      win:  _.isString(req.query.win) ? req.query.win : transientPrefix + ( (rk && rk.win)  || this._options.redirect.win ),
      fail: _.isString(req.query.fail) ? req.query.fail : transientPrefix + ( (rk && rk.fail) || this._options.redirect.fail ),
    }
  }

  return redirect
}

ServiceRouter.prototype._logerr = function(err) {
  if( err ) {
    return this._seneca.log('error', err)
  }
}

ServiceRouter.prototype._afterLogin = function(err, next, req, res) {
  if( err && !err.why ) return next(err)
  var self = this

  var context = req.seneca.cookies.get(this._options.transientprefix + 'context')
  res.seneca.cookies.set(this._options.transientprefix + 'context')

  var redirect = this._redirection(req, res, 'login')

  // req.user actually == {ok: , user: , login: }
  if( req.user && req.user.ok ) {
    // rename passport req.user prop
    req.seneca.user = req.user.user
    req.seneca.login = req.user.login

    this._adminLocal(req, req.seneca.user)

    res.seneca.cookies.set(this._options.tokenkey, req.seneca.login.token)

    if( '' != context ) {
      req.seneca.login.context = context
      req.seneca.login.save$(function(err) {
        self._do_respond(req, res, redirect, err)
      })
    } else {
      self._do_respond(req, res, redirect, undefined)
    }
  } else {
    //var out = {ok: false, why: (req.user&&req.user.why)||'no-user'}
    //delete req.user
    var out = {ok: false, why: err.why}
    if( redirect ) {
      req.seneca.log.debug('redirect', 'login', 'fail', redirect.fail)

      sendredirect( Http.FOUND, res, redirect.fail )
    } else {
      sendjson(Http.BAD_REQUEST, res, out)
    }
  }

}

ServiceRouter.prototype._do_respond = function(req, res, redirect, err) {
  if( err) return next(err)

  if( redirect ) {
    req.seneca.log.debug('redirect', 'login', 'win', redirect.win)
    sendredirect( Http.FOUND, res, redirect.win )
  } else {
    // FIX: this should call instance
    // FIX: how to handle errors here?
    this._seneca.act({role: this._plugin, cmd: 'clean', user: req.seneca.user, login: req.seneca.login}, function(err, out) {

      out.ok = true

      // FIX: should be provided by seneca-web
      sendjson( Http.OK, res, out )
    })
  }
}

ServiceRouter.prototype._respond = function(err, res, redirect, data) {

  if( redirect ) {
    //res.redirect( redirect )
    sendredirect(Http.FOUND, res, redirect)
  } else {
    var httpCode = Http.OK
    if(_.isNumber(err)) {
      httpCode = err
    } else if(_.isObject(err)) {
      httpCode = Http.INTERNAL_SERVER_ERROR
    } else if(!data.ok) {
      httpCode = Http.BAD_REQUEST
    }
    sendjson(httpCode, res, data)
  }
}

// TODO: move to seneca-web
function sendredirect(code, res, url) {
  res.writeHead(Http.MOVED_PERMANENTLY, {Location: url})
  res.end()
}

// TODO: move to seneca-web
function sendjson( code, res, out ) {
  // TODO: need killcircles
  var outjson = JSON.stringify(out)
  res.writeHead( code, {
    'Content-Type':   'application/json',
    'Cache-Control':  'private, max-age=0, no-cache, no-store',
    'Content-Length': buffer.Buffer.byteLength(outjson)
  })
  res.end( outjson )
}

module.exports = ServiceRouter
<|endoftext|>


<commit_before>var AbstractSerializer = require('./AbstractSerializer.js');

var SetSerializer = function SetSerializer(encoder, decoder) {
  this.encoder = encoder;
  this.decoder = decoder;
};

//Extend the AbstractSerializer
SetSerializer.prototype = Object.create(AbstractSerializer.prototype);
SetSerializer.prototype.AbstractSerializer = AbstractSerializer;

SetSerializer.prototype.serialize = function serialize(setsToSerialize) {
  var values, el, key, packedData, meta,
    _this = this,
      counter = {},
      attrNamesAndPossibilities = {};

  //creates a hash of keys with each value being an array
  setsToSerialize.forEach(function(obj, index){
    if (_this._isObject(obj)) {
      for (key in obj) {
        attrNamesAndPossibilities[key] = attrNamesAndPossibilities[key] || [];
        attrNamesAndPossibilities[key].push(obj[key]);
        counter[obj.id] = counter[obj.id] || index;
      }
      return attrNamesAndPossibilities && counter;
    }
  });

  //takes all values, returns only unique values, and add to array
  for (el in attrNamesAndPossibilities) {
    values = attrNamesAndPossibilities[el].filter(_this._onlyUniqueKeys);
    attrNamesAndPossibilities[el] = values;
  }

  // pack an array of all packed data
  packedData = this._packData(attrNamesAndPossibilities, setsToSerialize);

  meta = {
    // turn packedData to a plan JS Object
    serializedData: packedData.toPlainObject(),
    addedCounter: counter
  };

  return meta;
};

SetSerializer.prototype._packData = function _packData(preSerializedObj, setsToSerialize) {
  var _this = this,
    el,
    encoder = this.encoder,
    packer = encoder();

  // Adds packed attributes
  for (el in preSerializedObj) {
    packer.addAttribute({
      attrName: el,
      possibilities: preSerializedObj[el],
      maxChoices: 1
    })
  }
  // Packs the raw data
  packer.pack(setsToSerialize);

  return packer;
};

SetSerializer.prototype.deserialize = function deserialize(setsToDeserialize) {
  var unpackedData;

  unpackedData = this._unpackData(setsToDeserialize);
  return unpackedData;
};

SetSerializer.prototype._unpackData = function _unpackData(setsToDeserialize) {
  var _this = this,
    unpackedData,
    decoder = this.decoder,
    unpacker = decoder.Tamper();

  unpackedData = unpacker.unpackData(setsToDeserialize);

  return unpackedData
};

SetSerializer.prototype._isObject = function _isObject(item) {
  return item === Object(item);
};

SetSerializer.prototype._onlyUniqueKeys = function _onlyUniqueKeys(value, index, self) {
  return self.indexOf(value) === index;
};

SetSerializer.prototype._toMergedArray = function _toMergedArray(a, b) {
  return a.concat(b);
};

module.exports = SetSerializer;<commit_msg>Adds notes for .serialize()<commit_after>var AbstractSerializer = require('./AbstractSerializer.js');

var SetSerializer = function SetSerializer(encoder, decoder) {
  this.encoder = encoder;
  this.decoder = decoder;
};

//Extend the AbstractSerializer
SetSerializer.prototype = Object.create(AbstractSerializer.prototype);
SetSerializer.prototype.AbstractSerializer = AbstractSerializer;

/*
* @setsToSerialize, an array of objects that will be 'packed'
*
* serialize() (1) packs the entire set of objects by creating an encoded
* object with _packedData() and (2) keeps a count of all items in the
* set. This count will be used later to help the garbage collector
* choose which items to cleanup() and which order to clean them out
* as the algorithm is a FIFO, first in, first out.
*
* */
SetSerializer.prototype.serialize = function serialize(setToSerialize) {
  var values, el, key, packedData, meta,
    _this = this,
      orderCachedById = {},
      attrNamesAndPossibilities = {};

  //creates a hash of keys with each value being an array
  setToSerialize.forEach(function(obj, index){
    if (_this._isObject(obj)) {
      for (key in obj) {
        attrNamesAndPossibilities[key] = attrNamesAndPossibilities[key] || [];
        attrNamesAndPossibilities[key].push(obj[key]);
        orderCachedById[obj.id] = orderCachedById[obj.id] || index;
      }
      return attrNamesAndPossibilities && orderCachedById;
    }
  });

  //takes all values, returns only unique values, and add to array
  for (el in attrNamesAndPossibilities) {
    values = attrNamesAndPossibilities[el].filter(_this._onlyUniqueKeys);
    attrNamesAndPossibilities[el] = values;
  }

  // pack an array of all packed data
  packedData = this._packData(attrNamesAndPossibilities, setToSerialize);

  // includes packed data, which will be a JS object and the order in which
  // items in the set were cached by ID
  meta = {
    // turn packedData to a plan JS Object
    serializedData: packedData.toPlainObject(),
    addedCounter: orderCachedById
  };

  return meta;
};

SetSerializer.prototype._packData = function _packData(preSerializedObj, setToSerialize) {
  var _this = this,
    el,
    encoder = this.encoder,
    packer = encoder();

  // Adds packed attributes
  for (el in preSerializedObj) {
    packer.addAttribute({
      attrName: el,
      possibilities: preSerializedObj[el],
      maxChoices: 1
    })
  }
  // Packs the raw data
  packer.pack(setToSerialize);

  return packer;
};

SetSerializer.prototype.deserialize = function deserialize(setsToDeserialize) {
  var unpackedData;

  unpackedData = this._unpackData(setsToDeserialize);
  return unpackedData;
};

SetSerializer.prototype._unpackData = function _unpackData(setsToDeserialize) {
  var _this = this,
    unpackedData,
    decoder = this.decoder,
    unpacker = decoder.Tamper();

  unpackedData = unpacker.unpackData(setsToDeserialize);

  return unpackedData
};

SetSerializer.prototype._isObject = function _isObject(item) {
  return item === Object(item);
};

SetSerializer.prototype._onlyUniqueKeys = function _onlyUniqueKeys(value, index, self) {
  return self.indexOf(value) === index;
};

SetSerializer.prototype._toMergedArray = function _toMergedArray(a, b) {
  return a.concat(b);
};

module.exports = SetSerializer;<|endoftext|>


<commit_before>/* jslint node: true */

var fs           = require( 'fs' );
var path         = require( 'path' );
var EventEmitter = require( 'events' ).EventEmitter;
var util         = require( 'util' );
var fm           = require( 'front-matter' );
var glob         = require( 'glob' );
var es           = require( 'event-stream' );
var spawn        = require( 'child_process' ).spawn;
var waterfall    = require( 'async' ).waterfall;

function Documark( basePath ) {
	EventEmitter.call( this );

	// Determine path (and file)
	basePath = path.resolve( basePath || '.' );

	if( fs.statSync( basePath ).isFile() ) {
		this.path = path.dirname( basePath );
		this.file = basePath;
	} else {
		this.path = basePath;
		this.file = null;
	}

	this.config  = null;
	this.content = null;
	this.plugins = {};
	this.debug   = 0;
}

util.inherits( Documark, EventEmitter );

Documark.prototype.load = function() {
	// Get file contents
	var rawContent = fs.readFileSync( this.getFile(), { encoding: 'utf-8' } );

	// Get config and content
	var data = fm( rawContent );

	rawContent   = null;
	this.config  = data.attributes || {};
	this.content = data.body;

	// Load config.json if no front matter is available
	var configFile = path.join( this.getPath(), 'config.json' );

	if( fs.existsSync( configFile ) ) {
		this.config = require( configFile );
	}

	// Load plugins
	this.loadPlugins( this.getConfig().plugins );
};

Documark.prototype.loadPlugins = function( plugins ) {
	var self = this;

	if( typeof plugins === 'string' ) {
		plugins = [ plugins ];
	}
	if( ! Array.isArray( plugins ) ) {
		return;
	}

	plugins.forEach( function( plugin ) {
		// Check if not already loaded
		plugin = plugin.replace( /[^a-zA-Z0-9\-]/g, '' );

		if( self.plugins[ plugin ] !== undefined ) {
			return;
		}

		self.plugins[ plugin ] = require( 'documark-' + plugin )( self );
	} );
};

Documark.prototype.getPath = function() {
	return this.path;
};

Documark.prototype.getFile = function() {
	if( this.file === null ) {
		// Determine document file (if not given)
		var files = glob.sync( path.join( this.getPath(), 'document.*' ) );

		if( ! files.length ) {
			throw new Error( 'No document.* file found in ' + this.getPath() );
		}

		this.file = files[0];
	}

	return this.file;
};

Documark.prototype.getOutputFile = function( ext ) {
	var config   = this.getConfig();
	var file     = this.getFile();
	var filename = config.filename || config.title || path.basename( file, path.extname( file ) );

	if( typeof ext !== 'string' ) {
		ext = '.pdf';
	}

	return path.join( this.getPath(), filename + ext );
};

Documark.prototype.getConfig = function() {
	if( this.config === null ) {
		this.load();
	}

	return this.config;
};

Documark.prototype.getContent = function() {
	if( this.config === null ) {
		this.load();
	}

	return this.content;
};

Documark.prototype.getVerbosity = function() {
	return this.debug;
};

Documark.prototype.setVerbosity = function( level ) {
	this.debug = parseInt( level, 10 ) || 0;
};

Documark.prototype.compile = function( cb ) {
	var config  = this.getConfig();
	var options = [];

	if( typeof config.pdf === 'object' ) {
		for( var option in config.pdf ) {
			options.push( '--' + option );
			if( config.pdf[ option ] !== null ) {
				options.push( config.pdf[ option ] );
			}
		}
	}

	options.push( '-' ); // Read from stdin
	options.push( '-' ); // Write to stdout

	var pdf    = spawn( 'wkhtmltopdf', options, { cwd: this.getPath(), stdio: 'pipe' } );
	var input  = this._createContentStream();
	var output = fs.createWriteStream( this.getOutputFile() );

	pdf.stderr.pipe( process.stderr );

	input
		.pipe( this.getParser() )
		.pipe( this._createPluginHandler( 'html' ) )
		.pipe( this._createLogger( 1, this.getOutputFile( '.html' ) ) )
		.pipe( es.duplex( pdf.stdin, pdf.stdout ) )
		.pipe( output )
		;

	if( cb ) {
		output.on( 'finish', cb );
	}

	input.resume();
};

Documark.prototype.getParser = function() {
	var ext = path.extname( this.getFile() ).replace( /[^a-zA-Z0-9]/g, '' );

	try {
		return require( 'documark-parser-' + ext )( this );
	}
	catch( e ) {
		throw new Error( 'No parser found for .' + ext + ' files!' );
	}
};

Documark.prototype._createContentStream = function() {
	return es.through().pause().queue( this.getContent() ).end();
};

Documark.prototype._createPluginHandler = function( type ) {
	var self = this;

	return es.map( function( data, cb ) {
		// Collect plugins
		var plugins = [];

		self.emit( 'plugin:' + type, plugins );

		if( ! plugins.length ) {
			cb( null, data );
			return;
		}

		// Feed data
		plugins.unshift( function( cb ) { cb( null, data ); } );

		// Process plugins
		waterfall( plugins, cb );
	} );
};

Documark.prototype._createLogger = function( level, file ) {
	if( this.getVerbosity() < level ) {
		return es.through();
	}

	var log = fs.createWriteStream( file );

	return es.through( function( data ) {
		this.emit( 'data', data );
		log.write( data );
	}, function() {
		this.emit( 'end' );
		log.end();
	} );
};

module.exports = Documark;<commit_msg>Allow document base as base dir in wkhtmltopdf.<commit_after>/* jslint node: true */

var fs           = require( 'fs' );
var path         = require( 'path' );
var EventEmitter = require( 'events' ).EventEmitter;
var util         = require( 'util' );
var fm           = require( 'front-matter' );
var glob         = require( 'glob' );
var es           = require( 'event-stream' );
var spawn        = require( 'child_process' ).spawn;
var waterfall    = require( 'async' ).waterfall;

function Documark( basePath ) {
	EventEmitter.call( this );

	// Determine path (and file)
	basePath = path.resolve( basePath || '.' );

	if( fs.statSync( basePath ).isFile() ) {
		this.path = path.dirname( basePath );
		this.file = basePath;
	} else {
		this.path = basePath;
		this.file = null;
	}

	this.config  = null;
	this.content = null;
	this.plugins = {};
	this.debug   = 0;
}

util.inherits( Documark, EventEmitter );

Documark.prototype.load = function() {
	// Get file contents
	var rawContent = fs.readFileSync( this.getFile(), { encoding: 'utf-8' } );

	// Get config and content
	var data = fm( rawContent );

	rawContent   = null;
	this.config  = data.attributes || {};
	this.content = data.body;

	// Load config.json if no front matter is available
	var configFile = path.join( this.getPath(), 'config.json' );

	if( fs.existsSync( configFile ) ) {
		this.config = require( configFile );
	}

	// Load plugins
	this.loadPlugins( this.getConfig().plugins );
};

Documark.prototype.loadPlugins = function( plugins ) {
	var self = this;

	if( typeof plugins === 'string' ) {
		plugins = [ plugins ];
	}
	if( ! Array.isArray( plugins ) ) {
		return;
	}

	plugins.forEach( function( plugin ) {
		// Check if not already loaded
		plugin = plugin.replace( /[^a-zA-Z0-9\-]/g, '' );

		if( self.plugins[ plugin ] !== undefined ) {
			return;
		}

		self.plugins[ plugin ] = require( 'documark-' + plugin )( self );
	} );
};

Documark.prototype.getPath = function() {
	return this.path;
};

Documark.prototype.getFile = function() {
	if( this.file === null ) {
		// Determine document file (if not given)
		var files = glob.sync( path.join( this.getPath(), 'document.*' ) );

		if( ! files.length ) {
			throw new Error( 'No document.* file found in ' + this.getPath() );
		}

		this.file = files[0];
	}

	return this.file;
};

Documark.prototype.getOutputFile = function( ext ) {
	var config   = this.getConfig();
	var file     = this.getFile();
	var filename = config.filename || config.title || path.basename( file, path.extname( file ) );

	if( typeof ext !== 'string' ) {
		ext = '.pdf';
	}

	return path.join( this.getPath(), filename + ext );
};

Documark.prototype.getConfig = function() {
	if( this.config === null ) {
		this.load();
	}

	return this.config;
};

Documark.prototype.getContent = function() {
	if( this.config === null ) {
		this.load();
	}

	return this.content;
};

Documark.prototype.getVerbosity = function() {
	return this.debug;
};

Documark.prototype.setVerbosity = function( level ) {
	this.debug = parseInt( level, 10 ) || 0;
};

Documark.prototype.compile = function( cb ) {
	var config   = this.getConfig();
	var basePath = this.getPath();
	var options  = [
		'--allow', basePath
	];

	if( typeof config.pdf === 'object' ) {
		for( var option in config.pdf ) {
			options.push( '--' + option );
			if( config.pdf[ option ] !== null ) {
				options.push( config.pdf[ option ] );
			}
		}
	}

	options.push( '-' ); // Read from stdin
	options.push( '-' ); // Write to stdout

	var pdf    = spawn( 'wkhtmltopdf', options, { cwd: basePath, stdio: 'pipe' } );
	var input  = this._createContentStream();
	var output = fs.createWriteStream( this.getOutputFile() );

	pdf.stderr.pipe( process.stderr );

	input
		.pipe( this.getParser() )
		.pipe( this._createPluginHandler( 'html' ) )
		.pipe( this._createLogger( 1, this.getOutputFile( '.html' ) ) )
		.pipe( es.duplex( pdf.stdin, pdf.stdout ) )
		.pipe( output )
		;

	if( cb ) {
		output.on( 'finish', cb );
	}

	input.resume();
};

Documark.prototype.getParser = function() {
	var ext = path.extname( this.getFile() ).replace( /[^a-zA-Z0-9]/g, '' );

	try {
		return require( 'documark-parser-' + ext )( this );
	}
	catch( e ) {
		throw new Error( 'No parser found for .' + ext + ' files!' );
	}
};

Documark.prototype._createContentStream = function() {
	return es.through().pause().queue( this.getContent() ).end();
};

Documark.prototype._createPluginHandler = function( type ) {
	var self = this;

	return es.map( function( data, cb ) {
		// Collect plugins
		var plugins = [];

		self.emit( 'plugin:' + type, plugins );

		if( ! plugins.length ) {
			cb( null, data );
			return;
		}

		// Feed data
		plugins.unshift( function( cb ) { cb( null, data ); } );

		// Process plugins
		waterfall( plugins, cb );
	} );
};

Documark.prototype._createLogger = function( level, file ) {
	if( this.getVerbosity() < level ) {
		return es.through();
	}

	var log = fs.createWriteStream( file );

	return es.through( function( data ) {
		this.emit( 'data', data );
		log.write( data );
	}, function() {
		this.emit( 'end' );
		log.end();
	} );
};

module.exports = Documark;<|endoftext|>


<commit_before>'use strict';

const rp = require('request-promise-native');

let domoticzUrl;

// Call this before calling any other methods in this module
function init (url) {
  domoticzUrl = url;
}

function changeSwitch (switchIndex, command) {
  const domoticzCommandOptions = {
    method: 'GET',
    uri: `${domoticzUrl}/json.htm?type=command&param=switchlight&idx=${switchIndex}&switchcmd=${command}`,
    json: true
  };

  return rp(domoticzCommandOptions);
}

function turnOnSwitch (switchIndex) {
  return changeSwitch(switchIndex, 'On');
}

function turnOffSwitch (switchIndex) {
  return changeSwitch(switchIndex, 'Off');
}

module.exports = {
  init,
  turnOnSwitch,
  turnOffSwitch
};
<commit_msg>Fixed wrong url when getting device from Domoticz<commit_after>'use strict';

const rp = require('request-promise-native');

let domoticzUrl;

// Call this before calling any other methods in this module
function init (url) {
  domoticzUrl = url;
}

function changeSwitch (switchIndex, command) {
  const domoticzReadCommandOptions = {
    method: 'GET',
    uri: `${domoticzUrl}/json.htm?type=devices&rid=${switchIndex}`,
    json: true
  };

  const domoticzSetCommandOptions = {
    method: 'GET',
    uri: `${domoticzUrl}/json.htm?type=command&param=switchlight&idx=${switchIndex}&switchcmd=${command}`,
    json: true
  };

  return rp(domoticzReadCommandOptions)
    .then(devices => {
      if (devices.result[0].Status !== command) {
        return rp(domoticzSetCommandOptions);
      }
    });
}

function turnOnSwitch (switchIndex) {
  return changeSwitch(switchIndex, 'On');
}

function turnOffSwitch (switchIndex) {
  return changeSwitch(switchIndex, 'Off');
}

module.exports = {
  init,
  turnOnSwitch,
  turnOffSwitch
};
<|endoftext|>


<commit_before>
;(function(){

  'use strict';

  /**
   * Aliases
   */

  var indexOf = Array.prototype.indexOf;
  var getStyle = window.getComputedStyle;

  /**
   * CSS Classes
   */

  var overflowingChildClass = 'ellipsis-overflowing-child';
  var containerClass = 'ellipsis-set';

  /**
   * Error Messages
   */

  var errors = [
    'The ellipsis container must have line-height set on it'
  ];

  /**
   * Vendor Info
   */

  var vendor = getVendorData();

  /**
   * Initialize a new Ellipsis
   * instance with the given element.
   *
   * Options:
   *   - `container` A parent container element
   *   - `reRender` Forces a redraw after ellipsis applied
   *
   * @constructor
   * @param {Element} el
   * @param {Object} options
   * @api public
   */

  function Ellipsis(el, options) {
    if (!el) return;
    this.el = el;
    this.container = options && options.container;
    this.reRender = options && options.reRender;
  }

  /**
   * Measures the element and
   * finds the overflowing child.
   *
   * @return {Ellipsis}
   * @api public
   */

  Ellipsis.prototype.calc = function() {
    if (!this.el) return this;
    var style = getStyle(this.el);
    var size = getSize(this.el);

    this.columnHeight = size[1];
    this.columnCount = getColumnCount(style);
    this.columnGap = getColumnGap(style);
    this.columnWidth = size[0] / this.columnCount;
    this.lineHeight = getLineHeight(style);
    this.deltaHeight = size[1] % this.lineHeight;
    this.linesPerColumn = Math.floor(this.columnHeight / this.lineHeight);
    this.totalLines = this.linesPerColumn * this.columnCount;

    this.child = this.getOverflowingChild();

    return this;
  };

  /**
   * Clamps the overflowing child using
   * the information acquired from #calc().
   *
   * @return {Ellipsis}
   * @api public
   */

  Ellipsis.prototype.set = function() {
    if (!this.el || !this.child) return this;

    this.clampChild();
    siblingsAfter(this.child.el, { display: 'none' });
    this.markContainer();

    return this;
  };

  /**
   * Unclamps the overflowing child.
   *
   * @return {Ellipsis}
   * @api public
   */

  Ellipsis.prototype.unset = function() {
    if (!this.el || !this.child) return this;

    this.unclampChild(this.child);
    siblingsAfter(this.child.el, { display: '' });
    this.unmarkContainer();
    this.child = null;

    return this;
  };

  /**
   * Clears any references
   *
   * @return {Ellipsis}
   * @api public
   */

  Ellipsis.prototype.destroy = function() {
    this.el = this.child = null;
    return this;
  };

  /**
   * Returns the overflowing child with some
   * extra data required for clamping.
   *
   * @param  {Ellipsis} instance
   * @return {Object}
   * @api private
   */

  Ellipsis.prototype.getOverflowingChild = function() {
    var self = this;
    var child = {};
    var lineCounter = 0;

    // Loop over each child element
    each(this.el.children, function(el) {
      var lineCount, overflow, underflow;
      var startColumnIndex = Math.floor(lineCounter / self.linesPerColumn);

      // Get the line count of the
      // child and increment the counter
      lineCounter += lineCount = self.getLineCount(el);

      // If this is the overflowing child
      if (lineCounter >= self.totalLines) {
        overflow = lineCounter - self.totalLines;
        underflow = lineCount - overflow;

        child.el = el;
        child.clampedLines = underflow;
        child.clampedHeight = child.clampedLines * self.lineHeight;
        child.visibleColumnSpan = self.columnCount - startColumnIndex;
        child.applyTopMargin = self.shouldApplyTopMargin(child);

        return child;
      }
    });

    return child;
  };

  /**
   * Returns the number
   * of lines an element has.
   *
   * If the element is larger than
   * the column width we make the
   * assumption that this is FireFox
   * and the element is broken across
   * a column boundary. In this case
   * we have to get the height using
   * `getClientRects()`.
   *
   * @param  {Element} el
   * @return {Number}
   * @api private
   */

  Ellipsis.prototype.getLineCount = function(el) {
    return (el.offsetWidth > this.columnWidth)
      ? getLinesFromRects(el, this.lineHeight)
      : lineCount(el.clientHeight, this.lineHeight);
  };

  /**
   * If a container has been
   * declared we mark it with
   * a class for styling purposes.
   *
   * @api private
   */

  Ellipsis.prototype.markContainer = function() {
    if (!this.container) return;
    this.container.classList.add(containerClass);
    if (this.reRender) reRender(this.container);
  };

  /**
   * Removes the class
   * from the container.
   *
   * @api private
   */

  Ellipsis.prototype.unmarkContainer = function() {
    if (!this.container) return;
    this.container.classList.remove(containerClass);
    if (this.reRender) reRender(this.container);
  };

  /**
   * Determines whether top margin should be
   * applied to the overflowing child.
   *
   * This is to counteract an annoying
   * column-count/-webkit-box bug, whereby the
   * flexbox element falls into the delta are under
   * the previous sibling. Top margin keeps it
   * in the correct column.
   *
   * @param  {Element} el
   * @param  {Ellipsis} instance
   * @return {Boolean}
   * @api private
   */

  Ellipsis.prototype.shouldApplyTopMargin = function(child) {
    var el = child.el;

    // Dont't if it's not webkit
    if (!vendor.webkit) return;

    // Don't if it's a single column layout
    if (this.columnCount === 1) return;

    // Don't if the delta height is minimal
    if (this.deltaHeight <= 3) return;

    // Don't if it's the first child
    if (!el.previousElementSibling) return;

    // FINAL TEST: If the element is at the top or bottom of its
    // parent container then we require top margin.
    return (el.offsetTop === 0 || el.offsetTop === this.columnHeight);
  };

  /**
   * Clamps the child element to the set
   * height and lines.
   *
   * @param  {Object} child
   * @api private
   */

  Ellipsis.prototype.clampChild = function() {
    var child = this.child;
    if (!child || !child.el) return;

    child.el.style.height = child.clampedHeight + 'px';

    // Use webkit line clamp
    // for webkit browsers.
    if (vendor.webkit) {
      child.el.style.webkitLineClamp = child.clampedLines;
      child.el.style.display = '-webkit-box';
      child.el.style.webkitBoxOrient = 'vertical';
    }

    // Overflow hidden is only required
    // for single column containers as
    // multi-column containers overflow
    // to the right, so are not visible.
    // `overflow: hidden;` also messes
    // with column layout in Firefox.
    if (this.columnCount === 1) child.el.style.overflow = 'hidden';

    // Apply a top margin to fix webkit
    // column-count mixed with flexbox bug,
    // if we have decided it is neccessary.
    if (child.applyTopMargin) child.el.style.marginTop = '2em';

    // Add the overflowing child class as
    // a style hook
    child.el.classList.add(overflowingChildClass);

    // Non webkit borwsers get a helper
    // elment that is styled as an alternative
    // to the webkit-line-clamp ellipsis.
    if (!vendor.webkit) {
      child.helper = child.el.appendChild(this.helperElement());
    }
  };

  /**
   * Removes all clamping styles from
   * the overflowing child.
   *
   * @param  {Object} child
   * @api private
   */

  Ellipsis.prototype.unclampChild = function(child) {
    if (!child || !child.el) return;
    child.el.style.display = '';
    child.el.style.height = '';
    child.el.style.webkitLineClamp = '';
    child.el.style.webkitBoxOrient = '';
    child.el.style.marginTop = '';
    child.el.style.overflow = '';
    child.el.classList.remove(overflowingChildClass);

    if (child.helper) {
      child.helper.parentNode.removeChild(child.helper);
    }
  };

  /**
   * Creates the helper element
   * for non-webkit browsers.
   *
   * @return {Element}
   * @api private
   */

  Ellipsis.prototype.helperElement = function() {
    var el = document.createElement('span');
    var columns = this.child.visibleColumnSpan - 1;
    var rightOffset, marginRight;

    el.className = 'ellipsis-helper';
    el.style.display = 'block';
    el.style.height = this.lineHeight + 'px';
    el.style.position = 'absolute';
    el.style.bottom = 0;
    el.style.right = 0;

    // HACK: This is a work around to deal with
    // the wierdness of positioning elements
    // inside an element that is broken across
    // more than one column.
    if (vendor.js === 'Moz' && columns) {
      rightOffset = columns * 100;
      marginRight = -(columns * this.columnGap);
      el.style.right = '-' + rightOffset + '%';
      el.style.marginRight = marginRight + 'px';
      el.style.marginBottom = this.deltaHeight + 'px';
    }

    return el;
  };

  /**
   * Re-render with no setTimeout, boom!
   *
   * @param  {Element} el
   * @return void
   */
  function reRender(el) {
    el.style.display = 'none';
    var r = el.offsetTop;
    el.style.display = '';
  }

  /**
   * Sets the display property on
   * all siblingsafter the given element.
   *
   * Options:
   *   - `display` the css display type to use
   *
   * @param  {Node} el
   * @param  {Options} options
   * @return void
   */

  function siblingsAfter(el, options) {
    if (!el) return;
    var display = options && options.display;
    var siblings = el.parentNode.children;
    var index = indexOf.call(siblings, el);

    for (var i = index + 1, l = siblings.length; i < l; i++) {
      siblings[i].style.display = display;
    }
  }

  /**
   * Returns total line
   * count from a rect list.
   *
   * @param  {Element} el
   * @param  {Number} lineHeight
   * @return {Number}
   */

  function getLinesFromRects(el, lineHeight) {
    var rects = el.getClientRects();
    var lines = 0;

    each(rects, function(rect) {
      lines += lineCount(rect.height, lineHeight);
    });

    return lines;
  }

  /**
   * Calculates a line count
   * from the passed height.
   *
   * @param  {Number} height
   * @param  {Number} lineHeight
   * @return {Number}
   */

  function lineCount(height, lineHeight) {
    return Math.floor(height / lineHeight);
  }

  /**
   * Returns infomation about
   * the current vendor.
   *
   * @return {Object}
   */

  function getVendorData() {
    var el = document.createElement( "div" );
    var js = ["Webkit", "Moz", "O", "ms"];
    var css = ["-webkit-", "-moz-", "-o-", "-ms-"];
    for (var i = 0; i < js.length; i++ ) {
      if (js[i] + "ColumnCount" in el.style) {
        return {
          css: css[i],
          js: js[i],
          webkit: js[i] === 'Webkit',
          moz: js[i] === 'Moz'
        };
      }
    }
  }

  /**
   * Gets the column count of an
   * element using the vendor prefix.
   *
   * @param  {CSSStyleDeclaration} style  [description]
   * @return {Number}
   */

  function getColumnCount(style) {
    return parseInt(style[vendor.js + 'ColumnCount'], 10) || 1;
  }

  /**
   * Returns the gap between columns
   *
   * @param  {CSSStyleDeclaration} style
   * @return {Number}
   */

  function getColumnGap(style) {
    return parseInt(style[vendor.js + 'ColumnGap'], 10);
  }

  /**
   * Gets the line height
   * from the style declaration.
   *
   * @param  {CSSStyleDeclaration} style
   * @return {Number|null}
   */

  function getLineHeight(style) {
    var lineHeight = parseInt(style.lineHeight, 10);
    if (!lineHeight) throw new Error(errors[0]);

    return lineHeight;
  }

  /**
   * Returns the width and
   * height of the given element.
   *
   * @param  {Element} el
   * @return {Array}
   */

  function getSize(el) {
    return [el.offsetWidth, el.offsetHeight];
  }

  /**
   * Little iterator
   *
   * @param  {Array}   list
   * @param  {Function} fn
   */

  function each(list, fn) {
    for (var i = 0, l = list.length; i < l; i++) if (fn(list[i])) break;
  }

  /**
   * Expose `Ellipsis`
   */

  if (typeof exports === 'object') {
    module.exports = function(el, options) {
      return new Ellipsis(el, options);
    };

    module.exports.Ellipsis = Ellipsis;
  } else if (typeof define === 'function' && define.amd) {
    define(Ellipsis);
  } else {
    window.Ellipsis = Ellipsis;
  }

})();<commit_msg>Fix potential negative negative bug<commit_after>
;(function(){

  'use strict';

  /**
   * Aliases
   */

  var indexOf = Array.prototype.indexOf;
  var getStyle = window.getComputedStyle;

  /**
   * CSS Classes
   */

  var overflowingChildClass = 'ellipsis-overflowing-child';
  var containerClass = 'ellipsis-set';

  /**
   * Error Messages
   */

  var errors = [
    'The ellipsis container must have line-height set on it'
  ];

  /**
   * Vendor Info
   */

  var vendor = getVendorData();

  /**
   * Initialize a new Ellipsis
   * instance with the given element.
   *
   * Options:
   *   - `container` A parent container element
   *   - `reRender` Forces a redraw after ellipsis applied
   *
   * @constructor
   * @param {Element} el
   * @param {Object} options
   * @api public
   */

  function Ellipsis(el, options) {
    if (!el) return;
    this.el = el;
    this.container = options && options.container;
    this.reRender = options && options.reRender;
  }

  /**
   * Measures the element and
   * finds the overflowing child.
   *
   * @return {Ellipsis}
   * @api public
   */

  Ellipsis.prototype.calc = function() {
    if (!this.el) return this;
    var style = getStyle(this.el);
    var size = getSize(this.el);

    this.columnHeight = size[1];
    this.columnCount = getColumnCount(style);
    this.columnGap = getColumnGap(style);
    this.columnWidth = size[0] / this.columnCount;
    this.lineHeight = getLineHeight(style);
    this.deltaHeight = size[1] % this.lineHeight;
    this.linesPerColumn = Math.floor(this.columnHeight / this.lineHeight);
    this.totalLines = this.linesPerColumn * this.columnCount;

    this.child = this.getOverflowingChild();

    return this;
  };

  /**
   * Clamps the overflowing child using
   * the information acquired from #calc().
   *
   * @return {Ellipsis}
   * @api public
   */

  Ellipsis.prototype.set = function() {
    if (!this.el || !this.child) return this;

    this.clampChild();
    siblingsAfter(this.child.el, { display: 'none' });
    this.markContainer();

    return this;
  };

  /**
   * Unclamps the overflowing child.
   *
   * @return {Ellipsis}
   * @api public
   */

  Ellipsis.prototype.unset = function() {
    if (!this.el || !this.child) return this;

    this.unclampChild(this.child);
    siblingsAfter(this.child.el, { display: '' });
    this.unmarkContainer();
    this.child = null;

    return this;
  };

  /**
   * Clears any references
   *
   * @return {Ellipsis}
   * @api public
   */

  Ellipsis.prototype.destroy = function() {
    this.el = this.child = null;
    return this;
  };

  /**
   * Returns the overflowing child with some
   * extra data required for clamping.
   *
   * @param  {Ellipsis} instance
   * @return {Object}
   * @api private
   */

  Ellipsis.prototype.getOverflowingChild = function() {
    var self = this;
    var child = {};
    var lineCounter = 0;

    // Loop over each child element
    each(this.el.children, function(el) {
      var lineCount, overflow, underflow;
      var startColumnIndex = Math.floor(lineCounter / self.linesPerColumn);

      // Get the line count of the
      // child and increment the counter
      lineCounter += lineCount = self.getLineCount(el);

      // If this is the overflowing child
      if (lineCounter >= self.totalLines) {
        overflow = lineCounter - self.totalLines;
        underflow = lineCount - overflow;

        child.el = el;
        child.clampedLines = underflow;
        child.clampedHeight = child.clampedLines * self.lineHeight;
        child.visibleColumnSpan = self.columnCount - startColumnIndex;
        child.applyTopMargin = self.shouldApplyTopMargin(child);

        return child;
      }
    });

    return child;
  };

  /**
   * Returns the number
   * of lines an element has.
   *
   * If the element is larger than
   * the column width we make the
   * assumption that this is FireFox
   * and the element is broken across
   * a column boundary. In this case
   * we have to get the height using
   * `getClientRects()`.
   *
   * @param  {Element} el
   * @return {Number}
   * @api private
   */

  Ellipsis.prototype.getLineCount = function(el) {
    return (el.offsetWidth > this.columnWidth)
      ? getLinesFromRects(el, this.lineHeight)
      : lineCount(el.clientHeight, this.lineHeight);
  };

  /**
   * If a container has been
   * declared we mark it with
   * a class for styling purposes.
   *
   * @api private
   */

  Ellipsis.prototype.markContainer = function() {
    if (!this.container) return;
    this.container.classList.add(containerClass);
    if (this.reRender) reRender(this.container);
  };

  /**
   * Removes the class
   * from the container.
   *
   * @api private
   */

  Ellipsis.prototype.unmarkContainer = function() {
    if (!this.container) return;
    this.container.classList.remove(containerClass);
    if (this.reRender) reRender(this.container);
  };

  /**
   * Determines whether top margin should be
   * applied to the overflowing child.
   *
   * This is to counteract an annoying
   * column-count/-webkit-box bug, whereby the
   * flexbox element falls into the delta are under
   * the previous sibling. Top margin keeps it
   * in the correct column.
   *
   * @param  {Element} el
   * @param  {Ellipsis} instance
   * @return {Boolean}
   * @api private
   */

  Ellipsis.prototype.shouldApplyTopMargin = function(child) {
    var el = child.el;

    // Dont't if it's not webkit
    if (!vendor.webkit) return;

    // Don't if it's a single column layout
    if (this.columnCount === 1) return;

    // Don't if the delta height is minimal
    if (this.deltaHeight <= 3) return;

    // Don't if it's the first child
    if (!el.previousElementSibling) return;

    // FINAL TEST: If the element is at the top or bottom of its
    // parent container then we require top margin.
    return (el.offsetTop === 0 || el.offsetTop === this.columnHeight);
  };

  /**
   * Clamps the child element to the set
   * height and lines.
   *
   * @param  {Object} child
   * @api private
   */

  Ellipsis.prototype.clampChild = function() {
    var child = this.child;
    if (!child || !child.el) return;

    child.el.style.height = child.clampedHeight + 'px';

    // Use webkit line clamp
    // for webkit browsers.
    if (vendor.webkit) {
      child.el.style.webkitLineClamp = child.clampedLines;
      child.el.style.display = '-webkit-box';
      child.el.style.webkitBoxOrient = 'vertical';
    }

    // Overflow hidden is only required
    // for single column containers as
    // multi-column containers overflow
    // to the right, so are not visible.
    // `overflow: hidden;` also messes
    // with column layout in Firefox.
    if (this.columnCount === 1) child.el.style.overflow = 'hidden';

    // Apply a top margin to fix webkit
    // column-count mixed with flexbox bug,
    // if we have decided it is neccessary.
    if (child.applyTopMargin) child.el.style.marginTop = '2em';

    // Add the overflowing child class as
    // a style hook
    child.el.classList.add(overflowingChildClass);

    // Non webkit borwsers get a helper
    // elment that is styled as an alternative
    // to the webkit-line-clamp ellipsis.
    if (!vendor.webkit) {
      child.helper = child.el.appendChild(this.helperElement());
    }
  };

  /**
   * Removes all clamping styles from
   * the overflowing child.
   *
   * @param  {Object} child
   * @api private
   */

  Ellipsis.prototype.unclampChild = function(child) {
    if (!child || !child.el) return;
    child.el.style.display = '';
    child.el.style.height = '';
    child.el.style.webkitLineClamp = '';
    child.el.style.webkitBoxOrient = '';
    child.el.style.marginTop = '';
    child.el.style.overflow = '';
    child.el.classList.remove(overflowingChildClass);

    if (child.helper) {
      child.helper.parentNode.removeChild(child.helper);
    }
  };

  /**
   * Creates the helper element
   * for non-webkit browsers.
   *
   * @return {Element}
   * @api private
   */

  Ellipsis.prototype.helperElement = function() {
    var el = document.createElement('span');
    var columns = this.child.visibleColumnSpan - 1;
    var rightOffset, marginRight;

    el.className = 'ellipsis-helper';
    el.style.display = 'block';
    el.style.height = this.lineHeight + 'px';
    el.style.position = 'absolute';
    el.style.bottom = 0;
    el.style.right = 0;

    // HACK: This is a work around to deal with
    // the wierdness of positioning elements
    // inside an element that is broken across
    // more than one column.
    if (vendor.js === 'Moz' && columns) {
      rightOffset = -(columns * 100);
      marginRight = -(columns * this.columnGap);
      el.style.right = rightOffset + '%';
      el.style.marginRight = marginRight + 'px';
      el.style.marginBottom = this.deltaHeight + 'px';
    }

    return el;
  };

  /**
   * Re-render with no setTimeout, boom!
   *
   * @param  {Element} el
   * @return void
   */
  function reRender(el) {
    el.style.display = 'none';
    var r = el.offsetTop;
    el.style.display = '';
  }

  /**
   * Sets the display property on
   * all siblingsafter the given element.
   *
   * Options:
   *   - `display` the css display type to use
   *
   * @param  {Node} el
   * @param  {Options} options
   * @return void
   */

  function siblingsAfter(el, options) {
    if (!el) return;
    var display = options && options.display;
    var siblings = el.parentNode.children;
    var index = indexOf.call(siblings, el);

    for (var i = index + 1, l = siblings.length; i < l; i++) {
      siblings[i].style.display = display;
    }
  }

  /**
   * Returns total line
   * count from a rect list.
   *
   * @param  {Element} el
   * @param  {Number} lineHeight
   * @return {Number}
   */

  function getLinesFromRects(el, lineHeight) {
    var rects = el.getClientRects();
    var lines = 0;

    each(rects, function(rect) {
      lines += lineCount(rect.height, lineHeight);
    });

    return lines;
  }

  /**
   * Calculates a line count
   * from the passed height.
   *
   * @param  {Number} height
   * @param  {Number} lineHeight
   * @return {Number}
   */

  function lineCount(height, lineHeight) {
    return Math.floor(height / lineHeight);
  }

  /**
   * Returns infomation about
   * the current vendor.
   *
   * @return {Object}
   */

  function getVendorData() {
    var el = document.createElement( "div" );
    var js = ["Webkit", "Moz", "O", "ms"];
    var css = ["-webkit-", "-moz-", "-o-", "-ms-"];
    for (var i = 0; i < js.length; i++ ) {
      if (js[i] + "ColumnCount" in el.style) {
        return {
          css: css[i],
          js: js[i],
          webkit: js[i] === 'Webkit',
          moz: js[i] === 'Moz'
        };
      }
    }
  }

  /**
   * Gets the column count of an
   * element using the vendor prefix.
   *
   * @param  {CSSStyleDeclaration} style  [description]
   * @return {Number}
   */

  function getColumnCount(style) {
    return parseInt(style[vendor.js + 'ColumnCount'], 10) || 1;
  }

  /**
   * Returns the gap between columns
   *
   * @param  {CSSStyleDeclaration} style
   * @return {Number}
   */

  function getColumnGap(style) {
    return parseInt(style[vendor.js + 'ColumnGap'], 10);
  }

  /**
   * Gets the line height
   * from the style declaration.
   *
   * @param  {CSSStyleDeclaration} style
   * @return {Number|null}
   */

  function getLineHeight(style) {
    var lineHeight = parseInt(style.lineHeight, 10);
    if (!lineHeight) throw new Error(errors[0]);

    return lineHeight;
  }

  /**
   * Returns the width and
   * height of the given element.
   *
   * @param  {Element} el
   * @return {Array}
   */

  function getSize(el) {
    return [el.offsetWidth, el.offsetHeight];
  }

  /**
   * Little iterator
   *
   * @param  {Array}   list
   * @param  {Function} fn
   */

  function each(list, fn) {
    for (var i = 0, l = list.length; i < l; i++) if (fn(list[i])) break;
  }

  /**
   * Expose `Ellipsis`
   */

  if (typeof exports === 'object') {
    module.exports = function(el, options) {
      return new Ellipsis(el, options);
    };

    module.exports.Ellipsis = Ellipsis;
  } else if (typeof define === 'function' && define.amd) {
    define(Ellipsis);
  } else {
    window.Ellipsis = Ellipsis;
  }

})();<|endoftext|>


<commit_before>var path = require( 'path' );
var fs = require( 'fs' );
var _ = require( 'underscore' );
var mkpath = require( 'mkpath' );
var util = require( 'lz-node-utils' );

module.exports = function( handlebars ) {
	return function( config ) {

		config = _.defaults( config, {
			// directory from which to source the templtes
			// sourceDir:
			// (array) globbing pattern of files in sourceDir
			// source:
			// (string) directory in which to place translated files (optional)
			dest: '',
			// translator object, must expost function translate(templateContents, model)
			translator: {
				translate: function( templateContents ) {
					return templateContents;
				}
			},
			// The relative path of the partial from sourceDir, without the .tmpl extension
			partialPathToName: function( partialPath ) {
				return partialPath.replace( '.tmpl', '' );
			},
			// Something is considered a partial if the filename begins with `_`
			isPartial: function( filePath ) {
				return path.basename( filePath )[ 0 ] === '_';
			}
		} );

		// TODO: ensure that config.sourceDir exists

		var sourceFiles = listSourceFiles( config.source );

		// Get a list of sourceFiles that are considered partials
		var partialTemplates = _.filter( sourceFiles, determineIfPartial );

		// Register each partial with handlebars
		_.each( partialTemplates, function( filePath ) {
			var partialName = getPartialName( filePath );
			var partialContents = util.file.read( filePath );
			handlebars.registerPartial( partialName, partialContents );
		} );

		/***************************************************************************
		 ****************************    EXTERNAL API    ***************************
		 **************************************************************************/
		return {
			exportify: function( options ) {

				var toExport;

				// TODO: Clean up API, what's really needed here?
				var defaults = {
					source: '',
					dest: '',
					model: {},
					modelOpts: {},
					translateOpts: {}
				};

				if ( options && options.targets ) {
					toExport = _.map( options.targets, function( pageOpts ) {
						return _.defaults( {
							source: realPath( pageOpts.source ),
							dest: path.join( config.dest, pageOpts.dest ),
							model: getModel( pageOpts ),
							translateOpts: pageOpts.translateOpts
						}, defaults );
					} );
				} else if ( options ) {
					toExport = [ _.defaults( {
						source: realPath( options.source ),
						dest: path.join( config.dest, options.dest ),
						model: getModel( options ),
						translateOpts: options.translateOpts
					}, defaults ) ];
				} else {
					toExport = _.map( sourceFiles, function( sourcePath ) {
						var pathFromSrc = getPathFromSourceDir( sourcePath );
						var dest = path.join( config.dest, pathFromSrc );
						return _.defaults( {
							source: sourcePath,
							dest: dest,
							model: {}
						}, defaults );
					} );
				}

				_.each( toExport, function( paths ) {

					// Create the destination dir if it doesn't exist
					mkpath.sync( path.dirname( paths.dest ) );

					// Pass the file through the translator
					var translated = '';
					try {
						translated = config.translator.translate( util.file.read( paths.source ), paths.translateOpts, paths.model );
					} catch ( exception ) {
						console.log( 'Error translating file: ' + paths.source );
						console.log( exception.message );
						process.exit( 1 );
					}

					// Write the translated file to its destination
					fs.writeFileSync( path.join( process.cwd(), paths.dest ), translated );
				} );
			}
		};

		/***************************************************************************
		 ********************************    HELPERS    ****************************
		 **************************************************************************/
		function listSourceFiles( from ) {
			// For each item in config.source, prepend config.sourceDir
			// so that the pattern refers to an existing path.
			var retVal = _.map( from, realPath );
			// Pass the resulting array to util.file.expand to get a list of files
			retVal = util.file.expand( retVal );
			return retVal;
		}

		function getModel( pageOpts ) {
			if ( config.view ) {
				return config.view.getView( pageOpts.modelOpts, pageOpts.model );
			} else if ( pageOpts.model ) {
				return pageOpts.model;
			} else {
				return {};
			}
		}

		function realPath( to ) {
			return path.join( config.sourceDir, to );
		}

		function getPathFromSourceDir( to ) {
			var sourceDir = config.sourceDir;
			if ( sourceDir[ sourceDir.length - 1 ] !== '/' ) {
				sourceDir = sourceDir + '/';
			}
			return to.substr( sourceDir.length );
		}

		function determineIfPartial( filePath ) {
			return config.isPartial( getPathFromSourceDir( filePath ) );
		}

		function getPartialName( filePath ) {
			return config.partialPathToName( getPathFromSourceDir( filePath ) );
		}
	};
};
<commit_msg>First arg to translate is now source. UPDATE TRANSLATORS<commit_after>var path = require( 'path' );
var fs = require( 'fs' );
var _ = require( 'underscore' );
var mkpath = require( 'mkpath' );
var util = require( 'lz-node-utils' );

module.exports = function( handlebars ) {
	return function( config ) {

		config = _.defaults( config, {
			// directory from which to source the templtes
			// sourceDir:
			// (array) globbing pattern of files in sourceDir
			// source:
			// (string) directory in which to place translated files (optional)
			dest: '',
			// translator object, must expost function translate(templateContents, model)
			translator: {
				translate: function( templateContents ) {
					return templateContents;
				}
			},
			// The relative path of the partial from sourceDir, without the .tmpl extension
			partialPathToName: function( partialPath ) {
				return partialPath.replace( '.tmpl', '' );
			},
			// Something is considered a partial if the filename begins with `_`
			isPartial: function( filePath ) {
				return path.basename( filePath )[ 0 ] === '_';
			}
		} );

		// TODO: ensure that config.sourceDir exists

		var sourceFiles = listSourceFiles( config.source );

		// Get a list of sourceFiles that are considered partials
		var partialTemplates = _.filter( sourceFiles, determineIfPartial );

		// Register each partial with handlebars
		_.each( partialTemplates, function( filePath ) {
			var partialName = getPartialName( filePath );
			var partialContents = util.file.read( filePath );
			handlebars.registerPartial( partialName, partialContents );
		} );

		/***************************************************************************
		 ****************************    EXTERNAL API    ***************************
		 **************************************************************************/
		return {
			exportify: function( options ) {

				var toExport;

				// TODO: Clean up API, what's really needed here?
				var defaults = {
					source: '',
					dest: '',
					model: {},
					modelOpts: {},
					translateOpts: {}
				};

				if ( options && options.targets ) {
					toExport = _.map( options.targets, function( pageOpts ) {
						return _.defaults( {
							source: realPath( pageOpts.source ),
							dest: path.join( config.dest, pageOpts.dest ),
							model: getModel( pageOpts ),
							translateOpts: pageOpts.translateOpts
						}, defaults );
					} );
				} else if ( options ) {
					toExport = [ _.defaults( {
						source: realPath( options.source ),
						dest: path.join( config.dest, options.dest ),
						model: getModel( options ),
						translateOpts: options.translateOpts
					}, defaults ) ];
				} else {
					toExport = _.map( sourceFiles, function( sourcePath ) {
						var pathFromSrc = getPathFromSourceDir( sourcePath );
						var dest = path.join( config.dest, pathFromSrc );
						return _.defaults( {
							source: sourcePath,
							dest: dest,
							model: {}
						}, defaults );
					} );
				}

				_.each( toExport, function( paths ) {

					// Create the destination dir if it doesn't exist
					mkpath.sync( path.dirname( paths.dest ) );

					// Pass the file through the translator
					var translated = '';
					try {
						translated = config.translator.translate( paths.source, util.file.read( paths.source ), paths.translateOpts, paths.model );
					} catch ( exception ) {
						console.log( 'Error translating file: ' + paths.source );
						console.log( exception.message );
						process.exit( 1 );
					}

					// Write the translated file to its destination
					fs.writeFileSync( path.join( process.cwd(), paths.dest ), translated );
				} );
			}
		};

		/***************************************************************************
		 ********************************    HELPERS    ****************************
		 **************************************************************************/
		function listSourceFiles( from ) {
			// For each item in config.source, prepend config.sourceDir
			// so that the pattern refers to an existing path.
			var retVal = _.map( from, realPath );
			// Pass the resulting array to util.file.expand to get a list of files
			retVal = util.file.expand( retVal );
			return retVal;
		}

		function getModel( pageOpts ) {
			if ( config.view ) {
				return config.view.getView( pageOpts.modelOpts, pageOpts.model );
			} else if ( pageOpts.model ) {
				return pageOpts.model;
			} else {
				return {};
			}
		}

		function realPath( to ) {
			return path.join( config.sourceDir, to );
		}

		function getPathFromSourceDir( to ) {
			var sourceDir = config.sourceDir;
			if ( sourceDir[ sourceDir.length - 1 ] !== '/' ) {
				sourceDir = sourceDir + '/';
			}
			return to.substr( sourceDir.length );
		}

		function determineIfPartial( filePath ) {
			return config.isPartial( getPathFromSourceDir( filePath ) );
		}

		function getPartialName( filePath ) {
			return config.partialPathToName( getPathFromSourceDir( filePath ) );
		}
	};
};
<|endoftext|>


<commit_before>
module.exports = function (routes, crossVersionPaths) {
	return function (req, res, next) {
		var errorFound, acceptHeader = [];

		// Split and attempt to process accept header
		req.headers.accept.split(/[\s,]+/).forEach(function (acceptType) {
			var match,
				headerRegex = /^(\*|.+)\/((.+\.)+(v\d+)\+|(.*)\+)?(\*|\w+)(;.+)?$/g;
			acceptType = acceptType.trim();
			if (acceptType.length === 0) {
				return;
			}
			match = headerRegex.exec(acceptType);
			if (match) {
				acceptHeader.push({
					version: match[4],
					acceptType: match[1] + '/' + match[6]
				});
			} else {
				if (!errorFound) {
					res.status(400).send('Error: Accept header syntax is malformed');
				}
				errorFound = true;
			}
		});

		setFoundAcceptTypes(req, res, acceptHeader);
		modifyUrl(req, res, routes, acceptHeader, crossVersionPaths);

		if (!errorFound) {
			next();
		}
	};
};

// Set the found accept types
function setFoundAcceptTypes (req, res, acceptHeader) {
	req.headers.accept = acceptHeader.map(function (type) {
		return type.acceptType;
	}).join(' ');
}

// Modify the url path if:
	// it is specified in the first accept header type
	// and url does not use explicit versioning
	// and the url is not to a static page
	// and the specified version exists
function modifyUrl (req, res, routes, acceptHeader, crossVersionPaths) {
	var hasVersionRegex = /^\/v\d+\//g;
	if (acceptHeader.length > 0 && acceptHeader[0].version && hasVersionRegex.exec(req.url)) {
		var foundVersion, isStatic, routeKey, route;

		isStatic = crossVersionPaths.some(function (p) {
			return startsWith(req.url, p);
		});
		for (routeKey in routes) {
			route = routes[routeKey];
			if (route.version.path === '/' + acceptHeader[0].version) {
				foundVersion = route.version.path;
			}
		}
		if (!isStatic && foundVersion) {
			req.url = foundVersion + req.url;
		}
	}
}

function startsWith (value, strStart) {
	return value.lastIndexOf(strStart, 0) === 0;
}<commit_msg>- Match even more complicated mime types<commit_after>
module.exports = function (routes, crossVersionPaths) {
	return function (req, res, next) {
		var errorFound, acceptHeader = [];

		// Split and attempt to process accept header
		req.headers.accept.split(/[\s,]+/).forEach(function (acceptType) {
			var match,
				headerRegex = /^(\*|.+)\/((.+\.)+(v\d+)(\..+)*\+|(.*)\+)?(\*|\w+)(;.+)?$/g;
			acceptType = acceptType.trim();
			if (acceptType.length === 0) {
				return;
			}
			match = headerRegex.exec(acceptType);
			if (match) {
				acceptHeader.push({
					version: match[4],
					acceptType: match[1] + '/' + match[7]
				});
			} else {
				if (!errorFound) {
					res.status(400).send('Error: Accept header syntax is malformed');
				}
				errorFound = true;
			}
		});

		setFoundAcceptTypes(req, res, acceptHeader);
		modifyUrl(req, res, routes, acceptHeader, crossVersionPaths);

		if (!errorFound) {
			next();
		}
	};
};

// Set the found accept types
function setFoundAcceptTypes (req, res, acceptHeader) {
	req.headers.accept = acceptHeader.map(function (type) {
		return type.acceptType;
	}).join(' ');
}

// Modify the url path if:
	// it is specified in the first accept header type
	// and url does not use explicit versioning
	// and the url is not to a static page
	// and the specified version exists
function modifyUrl (req, res, routes, acceptHeader, crossVersionPaths) {
	var hasVersionRegex = /^\/v\d+\//g;
	if (acceptHeader.length > 0 && acceptHeader[0].version && hasVersionRegex.exec(req.url)) {
		var foundVersion, isStatic, routeKey, route;

		isStatic = crossVersionPaths.some(function (p) {
			return startsWith(req.url, p);
		});
		for (routeKey in routes) {
			route = routes[routeKey];
			if (route.version.path === '/' + acceptHeader[0].version) {
				foundVersion = route.version.path;
			}
		}
		if (!isStatic && foundVersion) {
			req.url = foundVersion + req.url;
		}
	}
}

function startsWith (value, strStart) {
	return value.lastIndexOf(strStart, 0) === 0;
}<|endoftext|>