<commit_before>/*jslint node: true */
var http = require('http'),
    fs = require('fs'),
    util = require('util'),
    url = require('url'),
    queryString = require('querystring'),
    YUI = require('yui3').YUI,
    Session = require('ajn-session').Session,
    Controller = require('./libs/Controller').Controller,
    Router = require('./libs/Router').Router;

var yuiConf = {
    modules: {
        'FinancistoApp': {
            fullpath: __dirname + '/js/FinancistoApp.js',
            requires: ['base', 'charts', 'io', 'node', 'event', 'tabview',
                'console', 'DataProvider', 'attribute']
        },
        'DataProvider': {
            fullpath: __dirname + '/js/DataProvider.js'
        },
        'console': {
            fullpath: __dirname + '/js/console.js'
        }
    }
};

function getTransactions(data, requestUrl, cb) {
    YUI(yuiConf).use('ajn', function (Y) {
        var output = '',
            days = requestUrl.query.days || null,
            date,
            allData,
            ajn;

        ajn = new Y.Ajn(data);
        allData = ajn.dao.get('json');
        output = ajn.dao.join(
            allData.transactions,
            allData.payee,
            {
                aField: 'payee_id',
                bField: '_id'
            },
            {
                aNames: {
                    '_id': 'transaction_id',
                    'from_amount': 'transaction_amount',
                    'from_account_id': 'transaction_account_id',
                    'datetime': 'datetime'
                },
                bNames: {
                    '_id': 'payee_id',
                    'title': 'payee_title'
                }
            }
        );
        output = ajn.dao.join(
            output,
            allData.account,
            {
                aField: 'transaction_account_id',
                bField: '_id'
            },
            {
                aNames: {
                    'transaction_id': 'transaction_id',
                    'transaction_amount': 'transaction_amount',
                    'datetime': 'datetime',
                    'payee_title': 'payee_title'
                },
                bNames: {
                    title: 'account_title',
                    'currency_id': 'currency_id'
                }
            }
        );
        output = ajn.dao.join(output, allData.currency, {
            aField: 'currency_id',
            bField: '_id'
        }, {
            aNames: {
                'transaction_id': 'transaction_id',
                'transaction_amount': 'transaction_amount',
                'datetime': 'datetime',
                'payee_title': 'payee_title',
                'account_title': 'account_title'
            },
            bNames: {
                'name': 'currency_name',
                'symbol': 'currency_symbol',
                title: 'currency_title'
            }
        });
        if (days) {
            date = new Date();
            date.setDate(date.getDate() - days);
            output = output.filter(function (item) {
                return date.getTime() <= item.datetime;
            });
        }
        cb(output);
    });
}

function getController(action) {
    var actionArr = action.split('/'),
        actionName = actionArr.slice(0, -1),
        dir = __dirname,
        Controller,
        controller;
    try {
        Controller = require(dir + '/actions/' + actionName)[actionArr.slice(-2, -1)];
        controller = new Controller();
    } catch (err) {
        console.log('cant get controller', err, action);
    }
    return controller;
}

var router = new Router();
router.get('/', 'Static/Index');
router.head('/', 'Static/Index');
router.get('/a.js', 'Static/JS');
router.head('/a.js', 'Static/JS');
router.get('/console.js', 'Static/JS');
router.head('/console.js', 'Static/JS');
router.get('/FinancistoApp.js', 'Static/JS');
router.head('/FinancistoApp.js', 'Static/JS');
router.get('/styles.css', 'Static/CSS');
router.head('/styles.css', 'Static/CSS');
router.get('/ajndao.js', 'Static/JS');
router.head('/ajndao.js', 'Static/JS');
router.get('/data', 'Data/Get');
router.put('/data', 'Data/Set');
router.del('/data', 'Data/Del');
router.get('/a.json', 'Data/Get');
router.get('/transactions.json', 'Transactions/Get');
function processRequest(req, res) {
    var server = new Controller(req, res),
        requestUrl = url.parse(req.url, true),
        requestData = '',
        session,
        d;

    console.log('process request', req.url, req.method);
    session = new Session(req, res);

    req.setEncoding('utf8');

    req.on('data', function (chunk) {
        requestData += chunk;
    });
    req.on('error', function (err) {
        server.serverError();
        console.log(err);
    });
    req.on('end', function () {
        var route = router.getRoute(requestUrl.pathname, req.method),
            controller;

        if (route) {
            controller = getController(route);
        }

        if (controller) {
            controller.setConf({
                jsDir: __dirname + '/js',
                cssDir: __dirname + '/css',
                templateDir: __dirname + '/templates'
            });
            controller.on('error', function (code) {
                if (code === 404) {
                    server.notFound();
                } else {
                    server.serverError();
                }
            });
            controller.on('setHeaders', function (headers) {
                server.sendResponse({
                    headers: headers
                });
            });
            controller.on('dataDone', function (data) {
                server.sendResponse(data);
            });
            controller.init({
                session: session
            });
            controller.callAction(route, req, queryString.parse(requestData));
        } else {
            console.log('router not found');
            server.notFound();
        }
        requestData = '';
    });
    req.on('close', function () {
        server = null;
    });

}

setInterval(function () {
    console.log('memory usage: ', process.memoryUsage());
}, 600000);

http.createServer(processRequest).listen(16444, '127.0.0.1');
console.log('Server running at http://127.0.0.1:16444/');
<commit_msg>Format statistics<commit_after>/*jslint node: true */
var http = require('http'),
    fs = require('fs'),
    util = require('util'),
    url = require('url'),
    queryString = require('querystring'),
    YUI = require('yui3').YUI,
    Session = require('ajn-session').Session,
    Controller = require('./libs/Controller').Controller,
    Router = require('./libs/Router').Router,
    ip = '127.0.0.1',
    port = 16444;

var yuiConf = {
    modules: {
        'FinancistoApp': {
            fullpath: __dirname + '/js/FinancistoApp.js',
            requires: ['base', 'charts', 'io', 'node', 'event', 'tabview',
                'console', 'DataProvider', 'attribute']
        },
        'DataProvider': {
            fullpath: __dirname + '/js/DataProvider.js'
        },
        'console': {
            fullpath: __dirname + '/js/console.js'
        }
    }
};

function showMemoryUsage() {
    var stat, rssInKB, heapTotalInKB, heapUsedInKB;

    stat = process.memoryUsage();
    rssInKB = stat.rss / 1024;
    heapTotalInKB = stat.heapTotal / 1024;
    heapUsedInKB = stat.heapUsed / 1024;

    console.log('memory usage: rss: %d KB, heap total: %d KB, heap used: %d KB',
                rssInKB, heapTotalInKB, heapUsedInKB);
}

function getTransactions(data, requestUrl, cb) {
    YUI(yuiConf).use('ajn', function (Y) {
        var output = '',
            days = requestUrl.query.days || null,
            date,
            allData,
            ajn;

        ajn = new Y.Ajn(data);
        allData = ajn.dao.get('json');
        output = ajn.dao.join(
            allData.transactions,
            allData.payee,
            {
                aField: 'payee_id',
                bField: '_id'
            },
            {
                aNames: {
                    '_id': 'transaction_id',
                    'from_amount': 'transaction_amount',
                    'from_account_id': 'transaction_account_id',
                    'datetime': 'datetime'
                },
                bNames: {
                    '_id': 'payee_id',
                    'title': 'payee_title'
                }
            }
        );
        output = ajn.dao.join(
            output,
            allData.account,
            {
                aField: 'transaction_account_id',
                bField: '_id'
            },
            {
                aNames: {
                    'transaction_id': 'transaction_id',
                    'transaction_amount': 'transaction_amount',
                    'datetime': 'datetime',
                    'payee_title': 'payee_title'
                },
                bNames: {
                    title: 'account_title',
                    'currency_id': 'currency_id'
                }
            }
        );
        output = ajn.dao.join(output, allData.currency, {
            aField: 'currency_id',
            bField: '_id'
        }, {
            aNames: {
                'transaction_id': 'transaction_id',
                'transaction_amount': 'transaction_amount',
                'datetime': 'datetime',
                'payee_title': 'payee_title',
                'account_title': 'account_title'
            },
            bNames: {
                'name': 'currency_name',
                'symbol': 'currency_symbol',
                title: 'currency_title'
            }
        });
        if (days) {
            date = new Date();
            date.setDate(date.getDate() - days);
            output = output.filter(function (item) {
                return date.getTime() <= item.datetime;
            });
        }
        cb(output);
    });
}

function getController(action) {
    var actionArr = action.split('/'),
        actionName = actionArr.slice(0, -1),
        dir = __dirname,
        Controller,
        controller;
    try {
        Controller = require(dir + '/actions/' + actionName)[actionArr.slice(-2, -1)];
        controller = new Controller();
    } catch (err) {
        console.log('cant get controller', err, action);
    }
    return controller;
}

var router = new Router();
router.get('/', 'Static/Index');
router.head('/', 'Static/Index');
router.get('/a.js', 'Static/JS');
router.head('/a.js', 'Static/JS');
router.get('/console.js', 'Static/JS');
router.head('/console.js', 'Static/JS');
router.get('/FinancistoApp.js', 'Static/JS');
router.head('/FinancistoApp.js', 'Static/JS');
router.get('/styles.css', 'Static/CSS');
router.head('/styles.css', 'Static/CSS');
router.get('/ajndao.js', 'Static/JS');
router.head('/ajndao.js', 'Static/JS');
router.get('/data', 'Data/Get');
router.put('/data', 'Data/Set');
router.del('/data', 'Data/Del');
router.get('/a.json', 'Data/Get');
router.get('/transactions.json', 'Transactions/Get');
function processRequest(req, res) {
    var server = new Controller(req, res),
        requestUrl = url.parse(req.url, true),
        requestData = '',
        session,
        d;

    console.log('process request', req.url, req.method);
    session = new Session(req, res);

    req.setEncoding('utf8');

    req.on('data', function (chunk) {
        requestData += chunk;
    });
    req.on('error', function (err) {
        server.serverError();
        console.log(err);
    });
    req.on('end', function () {
        var route = router.getRoute(requestUrl.pathname, req.method),
            controller;

        if (route) {
            controller = getController(route);
        }

        if (controller) {
            controller.setConf({
                jsDir: __dirname + '/js',
                cssDir: __dirname + '/css',
                templateDir: __dirname + '/templates'
            });
            controller.on('error', function (code) {
                if (code === 404) {
                    server.notFound();
                } else {
                    server.serverError();
                }
            });
            controller.on('setHeaders', function (headers) {
                server.sendResponse({
                    headers: headers
                });
            });
            controller.on('dataDone', function (data) {
                server.sendResponse(data);
            });
            controller.init({
                session: session
            });
            controller.callAction(route, req, queryString.parse(requestData));
        } else {
            console.log('router not found');
            server.notFound();
        }
        requestData = '';
    });
    req.on('close', function () {
        server = null;
    });

}

setInterval(showMemoryUsage, 600000);

http.createServer(processRequest).listen(port, ip);
console.log('Server running at http://%s:%d', ip, port);
showMemoryUsage();
<|endoftext|>


<commit_before>'use strict'
var u          = require('./util')
var Api        = require('./api')
var Muxrpc     = require('muxrpc')
var pull       = require('pull-stream')
var Rate       = require('pull-rate')

var MultiServer = require('multiserver')
var Inactive   = require('pull-inactivity')

var debug = require('debug')('secret-stack')

function isFunction (f) { return 'function' === typeof f }
function isString (s) { return 'string' === typeof s }
function isObject (o) { return o && 'object' === typeof o && !Array.isArray(o) }

function toBase64 (s) {
  if(isString(s)) return s
  else s.toString('base64') //assume a buffer
}

function each(obj, iter) {
  if(Array.isArray(obj)) return obj.forEach(iter)
  for(var k in obj) iter(obj[k], k, obj)
}

function coearseAddress (address) {
  if(isObject(address)) {
    var protocol = 'net'
    if (address.host.endsWith(".onion"))
        protocol = 'onion'
    return [protocol, address.host, address.port].join(':') +'~'+['shs', toBase64(address.key)].join(':')
  }
  return address
}

var ip = require('ip')

function parse(addr) {
  var parts = addr.split('~')[0].split(':')
  var protocol = parts[0], host = parts[1]
  return {
    protocol: protocol,
    group: (ip.isLoopback(host) || !host) ? 'loopback' : ip.isPrivate(host) ? 'local' : 'internet',
    host: host
  }
}

function msLogger (stream) {
  var meta = {tx: 0, rx:0, pk: 0}
  stream = Rate(stream, function (len, up) {
    meta.pk ++
    if(up) meta.tx += len
    else meta.rx += len
  })
  stream.meta = meta
  return stream
}

//opts must have appKey
module.exports = function (opts) {
  //this weird thing were some config is loaded first, then the rest later... not necessary.
  var _opts = opts
  var appKey = (opts && opts.caps && opts.caps.shs || opts.appKey)

  opts.permissions = opts.permissions || {}

  var create = Api(opts.permissions ? [{
    permissions: opts.permissions,
    init: function () {}
  }]: null)

  return create
  .use({
    manifest: {
      auth: 'async',
      address: 'sync',
      manifest: 'sync',
      multiserver: {
        scopes: 'sync',
        parse: 'sync',
        address: 'sync'
      }
    },
    init: function (api, opts, permissions, manifest) {

      // defaults
      opts.appKey = opts.appKey || appKey

      //XXX: LEGACY CRUFT - TIMEOUTS
      var defaultTimeout = opts.defaultTimeout || 5e3 // 5 seconds.
      var timeout_inactivity

      if(opts.timers && !isNaN(opts.timers.inactivity))
        timeout_inactivity = opts.timers.inactivity

      // if opts.timers are set, pick a longer default
      // but if not, set a short default (as needed in the tests)
      timeout_inactivity = timeout_inactivity || (opts.timers ? 600e3 : 5e3)

      if (!opts.connections) {
        var net_in = { scope: ["device", "local", "public"], "transform": "shs"}
        var net_out = { "transform": "shs"}
        // avoid setting properties to value `undefined`
        if (opts.host) net_in.host = opts.host
        if (opts.port) {
          net_in.port = opts.port
        }
        opts.connections = {
          incoming: {
            net: [net_in]
          },
          outgoing: {
            net: [net_out]
          }
        }
      }
      var peers = api.peers = {}

      var transports = []

      var transforms = [
        //function () { return shs }
      ]

      var server, ms, ms_client

      function setupMultiserver () {
        if(api.closed) return
        if(server) return server
        if(transforms.length < 1)
          throw new Error('secret-stack needs at least 1 transform protocol')

        var server_suites = []
        var client_suites = []

        for (var incTransportType in opts.connections.incoming) {
          opts.connections.incoming[incTransportType].forEach(function (conf) {
            transforms.forEach(function (transform) {
              transports.forEach(function (transport) {
                if (transport.name == incTransportType && transform.name == conf.transform) {
                  var trans = transport.create(conf)
                  if(trans.scope() !== conf.scope)
                    throw new Error('transport:'+transport.name +' did not remember scope, expected:' + conf.scope + ' got:'+trans.scope())
                  debug('creating server %s %s host=%s port=%d scope=%s', incTransportType, transform.name, conf.host, conf.port, conf.scope || 'undefined')
                  server_suites.push([
                    transport.create(conf),
                    transform.create()
                  ])
                }
              })
            })
          })
        }

        for (var outTransportType in opts.connections.outgoing) {
          opts.connections.outgoing[outTransportType].forEach(function (conf) {
            transforms.forEach(function (transform) {
              transports.forEach(function (transport) {
                if (transport.name == outTransportType && transform.name == conf.transform)
                  client_suites.push([
                    transport.create(conf),
                    transform.create()
                  ])
              })
            })
          })
        }

        ms_client = MultiServer(client_suites)

        ms = MultiServer(server_suites)
        server = ms.server(setupRPC)
        if(!server) throw new Error('expected server')
        return server
      }

      setImmediate(setupMultiserver)

      function setupRPC (stream, manf, isClient) {
        var rpc = Muxrpc(create.manifest, manf || create.manifest)(api, stream.auth === true ? create.permissions.anonymous : stream.auth)
        var rpcStream = rpc.createStream()
        rpc.id = '@'+u.toId(stream.remote)
        if(timeout_inactivity > 0 && api.id !== rpc.id) rpcStream = Inactive(rpcStream, timeout_inactivity)
        rpc.meta = stream.meta

        pull(stream, rpcStream, stream)

        //keep track of current connections.
        if(!peers[rpc.id]) peers[rpc.id] = []
        peers[rpc.id].push(rpc)
        rpc.once('closed', function () {
          peers[rpc.id].splice(peers[rpc.id].indexOf(rpc), 1)
        })

        api.emit('rpc:connect', rpc, !!isClient)

        return rpc
      }

      return {
        config: opts,
        //can be called remotely.
        auth: function (pub, cb) { cb() },
        address: function (scope) {
          return api.getAddress(scope)
        },
        getAddress: function (scope) {
          setupMultiserver()
          return ms.stringify(scope) || null
        },
        manifest: function () {
          return create.manifest
        },
        getManifest: function () {
          return this.manifest()
        },
        //cannot be called remote.
        connect: function (address, cb) {
          setupMultiserver()
          ms_client.client(coearseAddress(address), function (err, stream) {
            return err ? cb(err) : cb(null, setupRPC(stream, null, true))
          })
        },

        multiserver: {
          transport: function (transport) {
            if(server) throw new Error('cannot add protocol after server initialized')
            if(!isObject(transport) && isString(transport.name) && isFunction(transport.create))
              throw new Error('transport must be {name: string, create: function}')
            debug('Adding transport %s', transport.name)
            transports.push(transport); return this
          },
          transform: function (transform) {
            if(!isObject(transform) && isString(transform.name) && isFunction(transform.create))
              throw new Error('transform must be {name: string, create: function}')
            debug('Adding transform %s', transform.name)
            transforms.push(transform); return this
          },
          parse: function (str) {
            return ms.parse(str)
          },
          scopes: function () {
            return ms.scopes()
          },
          address: function (scope) {
            setupMultiserver()
            return ms.stringify(scope) || null
          }
        },
        close: function (err, cb) {
          if(isFunction(err)) cb = err, err = null
          api.closed = true
          if(!server) cb && cb()
          else {
            ;(server.close || server)(function (err) {
              api.emit('close', err)
              cb && cb(err)
            })
          }

          if(err) {
            each(peers, function (connections, id) {
              each(connections, function (rpc) {
                rpc.close(err)
              })
            })
          }
        }
      }
    }
  })
  //default network plugins
  .use(require('./plugins/net'))
  .use(require('./plugins/shs'))
}

<commit_msg>remove scopes method, didn't end up exporting it from multiserver<commit_after>'use strict'
var u          = require('./util')
var Api        = require('./api')
var Muxrpc     = require('muxrpc')
var pull       = require('pull-stream')
var Rate       = require('pull-rate')

var MultiServer = require('multiserver')
var Inactive   = require('pull-inactivity')

var debug = require('debug')('secret-stack')

function isFunction (f) { return 'function' === typeof f }
function isString (s) { return 'string' === typeof s }
function isObject (o) { return o && 'object' === typeof o && !Array.isArray(o) }

function toBase64 (s) {
  if(isString(s)) return s
  else s.toString('base64') //assume a buffer
}

function each(obj, iter) {
  if(Array.isArray(obj)) return obj.forEach(iter)
  for(var k in obj) iter(obj[k], k, obj)
}

function coearseAddress (address) {
  if(isObject(address)) {
    var protocol = 'net'
    if (address.host.endsWith(".onion"))
        protocol = 'onion'
    return [protocol, address.host, address.port].join(':') +'~'+['shs', toBase64(address.key)].join(':')
  }
  return address
}

var ip = require('ip')

function parse(addr) {
  var parts = addr.split('~')[0].split(':')
  var protocol = parts[0], host = parts[1]
  return {
    protocol: protocol,
    group: (ip.isLoopback(host) || !host) ? 'loopback' : ip.isPrivate(host) ? 'local' : 'internet',
    host: host
  }
}

function msLogger (stream) {
  var meta = {tx: 0, rx:0, pk: 0}
  stream = Rate(stream, function (len, up) {
    meta.pk ++
    if(up) meta.tx += len
    else meta.rx += len
  })
  stream.meta = meta
  return stream
}

//opts must have appKey
module.exports = function (opts) {
  //this weird thing were some config is loaded first, then the rest later... not necessary.
  var _opts = opts
  var appKey = (opts && opts.caps && opts.caps.shs || opts.appKey)

  opts.permissions = opts.permissions || {}

  var create = Api(opts.permissions ? [{
    permissions: opts.permissions,
    init: function () {}
  }]: null)

  return create
  .use({
    manifest: {
      auth: 'async',
      address: 'sync',
      manifest: 'sync',
      multiserver: {
        parse: 'sync',
        address: 'sync'
      }
    },
    init: function (api, opts, permissions, manifest) {

      // defaults
      opts.appKey = opts.appKey || appKey

      //XXX: LEGACY CRUFT - TIMEOUTS
      var defaultTimeout = opts.defaultTimeout || 5e3 // 5 seconds.
      var timeout_inactivity

      if(opts.timers && !isNaN(opts.timers.inactivity))
        timeout_inactivity = opts.timers.inactivity

      // if opts.timers are set, pick a longer default
      // but if not, set a short default (as needed in the tests)
      timeout_inactivity = timeout_inactivity || (opts.timers ? 600e3 : 5e3)

      if (!opts.connections) {
        var net_in = { scope: ["device", "local", "public"], "transform": "shs"}
        var net_out = { "transform": "shs"}
        // avoid setting properties to value `undefined`
        if (opts.host) net_in.host = opts.host
        if (opts.port) {
          net_in.port = opts.port
        }
        opts.connections = {
          incoming: {
            net: [net_in]
          },
          outgoing: {
            net: [net_out]
          }
        }
      }
      var peers = api.peers = {}

      var transports = []

      var transforms = [
        //function () { return shs }
      ]

      var server, ms, ms_client

      function setupMultiserver () {
        if(api.closed) return
        if(server) return server
        if(transforms.length < 1)
          throw new Error('secret-stack needs at least 1 transform protocol')

        var server_suites = []
        var client_suites = []

        for (var incTransportType in opts.connections.incoming) {
          opts.connections.incoming[incTransportType].forEach(function (conf) {
            transforms.forEach(function (transform) {
              transports.forEach(function (transport) {
                if (transport.name == incTransportType && transform.name == conf.transform) {
                  var trans = transport.create(conf)
                  if(trans.scope() !== conf.scope)
                    throw new Error('transport:'+transport.name +' did not remember scope, expected:' + conf.scope + ' got:'+trans.scope())
                  debug('creating server %s %s host=%s port=%d scope=%s', incTransportType, transform.name, conf.host, conf.port, conf.scope || 'undefined')
                  server_suites.push([
                    transport.create(conf),
                    transform.create()
                  ])
                }
              })
            })
          })
        }

        for (var outTransportType in opts.connections.outgoing) {
          opts.connections.outgoing[outTransportType].forEach(function (conf) {
            transforms.forEach(function (transform) {
              transports.forEach(function (transport) {
                if (transport.name == outTransportType && transform.name == conf.transform)
                  client_suites.push([
                    transport.create(conf),
                    transform.create()
                  ])
              })
            })
          })
        }

        ms_client = MultiServer(client_suites)

        ms = MultiServer(server_suites)
        server = ms.server(setupRPC)
        if(!server) throw new Error('expected server')
        return server
      }

      setImmediate(setupMultiserver)

      function setupRPC (stream, manf, isClient) {
        var rpc = Muxrpc(create.manifest, manf || create.manifest)(api, stream.auth === true ? create.permissions.anonymous : stream.auth)
        var rpcStream = rpc.createStream()
        rpc.id = '@'+u.toId(stream.remote)
        if(timeout_inactivity > 0 && api.id !== rpc.id) rpcStream = Inactive(rpcStream, timeout_inactivity)
        rpc.meta = stream.meta

        pull(stream, rpcStream, stream)

        //keep track of current connections.
        if(!peers[rpc.id]) peers[rpc.id] = []
        peers[rpc.id].push(rpc)
        rpc.once('closed', function () {
          peers[rpc.id].splice(peers[rpc.id].indexOf(rpc), 1)
        })

        api.emit('rpc:connect', rpc, !!isClient)

        return rpc
      }

      return {
        config: opts,
        //can be called remotely.
        auth: function (pub, cb) { cb() },
        address: function (scope) {
          return api.getAddress(scope)
        },
        getAddress: function (scope) {
          setupMultiserver()
          return ms.stringify(scope) || null
        },
        manifest: function () {
          return create.manifest
        },
        getManifest: function () {
          return this.manifest()
        },
        //cannot be called remote.
        connect: function (address, cb) {
          setupMultiserver()
          ms_client.client(coearseAddress(address), function (err, stream) {
            return err ? cb(err) : cb(null, setupRPC(stream, null, true))
          })
        },

        multiserver: {
          transport: function (transport) {
            if(server) throw new Error('cannot add protocol after server initialized')
            if(!isObject(transport) && isString(transport.name) && isFunction(transport.create))
              throw new Error('transport must be {name: string, create: function}')
            debug('Adding transport %s', transport.name)
            transports.push(transport); return this
          },
          transform: function (transform) {
            if(!isObject(transform) && isString(transform.name) && isFunction(transform.create))
              throw new Error('transform must be {name: string, create: function}')
            debug('Adding transform %s', transform.name)
            transforms.push(transform); return this
          },
          parse: function (str) {
            return ms.parse(str)
          },
          address: function (scope) {
            setupMultiserver()
            return ms.stringify(scope) || null
          }
        },
        close: function (err, cb) {
          if(isFunction(err)) cb = err, err = null
          api.closed = true
          if(!server) cb && cb()
          else {
            ;(server.close || server)(function (err) {
              api.emit('close', err)
              cb && cb(err)
            })
          }

          if(err) {
            each(peers, function (connections, id) {
              each(connections, function (rpc) {
                rpc.close(err)
              })
            })
          }
        }
      }
    }
  })
  //default network plugins
  .use(require('./plugins/net'))
  .use(require('./plugins/shs'))
}

<|endoftext|>


<commit_before>const fs = require('fs');
const path = require('path');
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const methodOverride = require('method-override');
const nodeSass = require('node-sass-middleware');
const expressHandlebars = require('express-handlebars');

const PORT = process.env.PORT || 80;
const HOST = '0.0.0.0';

app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(bodyParser.json());
app.use(methodOverride());

app.use(nodeSass({
    src: path.join(__dirname, '/sass'),
    dest: path.join(__dirname, '/public/css'),
    debug: false,
    indentedSyntax: true,
    outputStyle: 'compressed',
    prefix: '/css'
}));

app.use(express.static('public'));

app.set('views', path.join(__dirname, '/views'));
app.engine('handlebars', expressHandlebars({
    defaultLayout: 'main'
}));
app.set('view engine', 'handlebars');

app.get('/:page', (req, res) => {
    res.render(req.params.page.toString().trim().toLowerCase(), {
        title: req.params.page.toString().trim()
    });
});

app.get('/', (req, res) => {
    return res.render('index', {
        title: 'Home'
    });
});

app.use((err, req, res, next) => {
    if (err.message.search(/Failed to lookup view "(.*)" in views directory/g) > -1 || err.status === 404)
		return res.status(404).render('404', {
	        title: '404 Not Page Found',
	        url: req.url
	    });
	console.error('Unexpected Error', err);
    return res.status(500).send('An unexpected error occured.');
});

app.listen(PORT, HOST, () => {
    console.log(`syfy-website listening on http://${HOST}:${PORT}`);
});
<commit_msg>Local 404 handling<commit_after>const fs = require('fs');
const path = require('path');
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const methodOverride = require('method-override');
const nodeSass = require('node-sass-middleware');
const expressHandlebars = require('express-handlebars');

const PORT = process.env.PORT || 80;
const HOST = '0.0.0.0';

app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(bodyParser.json());
app.use(methodOverride());

app.use(nodeSass({
    src: path.join(__dirname, '/sass'),
    dest: path.join(__dirname, '/public/css'),
    debug: false,
    indentedSyntax: true,
    outputStyle: 'compressed',
    prefix: '/css'
}));

app.use(express.static('public'));

app.set('views', path.join(__dirname, '/views'));
app.engine('handlebars', expressHandlebars({
    defaultLayout: 'main'
}));
app.set('view engine', 'handlebars');

app.get('/:page', (req, res) => {
    return res.render(req.params.page.toString().trim().toLowerCase(), {
        title: req.params.page.toString().trim()
    }, (err, html) => {
		if (err) {
			return res.render('404', {
		        title: '404 Not Found',
				url: req.url
		    }, (err, html) => {
				if (err) {
					return res.status(500).send('Unexpected error occured after you encountered a 404.');
				}
				return res.status(404).send(html);
			});
		}
		res.status(200).send(html);
	});
});

app.get('/', (req, res) => {
    return res.render('index', {
        title: 'Home'
    });
});

// app.use((err, req, res, next) => {
//     if (err.message.search(/Failed to lookup view "(.*)" in views directory/g) > -1 || err.status === 404)
// 		return res.status(404).render('404', {
// 	        title: '404 Not Page Found',
// 	        url: req.url
// 	    });
// 	console.error('Unexpected Error', err);
//     return res.status(500).send('An unexpected error occured.');
// });

app.listen(PORT, HOST, () => {
    console.log(`syfy-website listening on http://${HOST}:${PORT}`);
});
<|endoftext|>


<commit_before>// Source: https://github.com/kangax/html-minifier/issues/63
const htmlBooleanAttributes = new Set([
    'allowfullscreen',
    'allowpaymentrequest',
    'allowtransparency',
    'async',
    'autofocus',
    'autoplay',
    'checked',
    'compact',
    'controls',
    'crossorigin',
    'declare',
    'default',
    'defaultchecked',
    'defaultmuted',
    'defaultselected',
    'defer',
    'disabled',
    'enabled',
    'formnovalidate',
    'hidden',
    'indeterminate',
    'inert',
    'ismap',
    'itemscope',
    'loop',
    'multiple',
    'muted',
    'nohref',
    'noresize',
    'noshade',
    'novalidate',
    'nowrap',
    'open',
    'pauseonexit',
    'readonly',
    'required',
    'reversed',
    'scoped',
    'seamless',
    'selected',
    'sortable',
    'truespeed',
    'typemustmatch',
    'visible'
]);

const amphtmlBooleanAttributes = new Set([
    '⚡',
    'amp',
    '⚡4ads',
    'amp4ads',
    '⚡4email',
    'amp4email',

    'amp-custom',
    'amp-boilerplate',
    'amp4ads-boilerplate',
    'amp4email-boilerplate',

    'allow-blocked-ranges',
    'amp-access-hide',
    'amp-access-template',
    'amp-keyframes',
    'animate',
    'arrows',
    'data-block-on-consent',
    'data-enable-refresh',
    'data-multi-size',
    'date-template',
    'disable-double-tap',
    'disable-session-states',
    'disableremoteplayback',
    'dots',
    'expand-single-section',
    'expanded',
    'fallback',
    'first',
    'fullscreen',
    'inline',
    'lightbox',
    'noaudio',
    'noautoplay',
    'noloading',
    'once',
    'open-after-clear',
    'open-after-select',
    'open-button',
    'placeholder',
    'preload',
    'reset-on-refresh',
    'reset-on-resize',
    'resizable',
    'rotate-to-fullscreen',
    'second',
    'standalone',
    'stereo',
    'submit-error',
    'submit-success',
    'submitting',
    'subscriptions-actions',
    'subscriptions-dialog'
]);

export default function collapseBooleanAttributes(tree, options, moduleOptions) {
    tree.match({attrs: true}, node => {
        for (let attrName of Object.keys(node.attrs)) {
            if (!node.tag) {
                continue;
            }

            if (node.tag.search('a-') === 0 && attrName === 'visible') {
                continue;
            }

            if (htmlBooleanAttributes.has(attrName)) {
                node.attrs[attrName] = true;
            }
            if (moduleOptions.amphtml && node.attrs[attrName] === '' && amphtmlBooleanAttributes.has(attrName)) {
                node.attrs[attrName] = true;
            }
        }

        return node;
    });

    return tree;
}
<commit_msg>Remove crossorigin<commit_after>// Source: https://github.com/kangax/html-minifier/issues/63
const htmlBooleanAttributes = new Set([
    'allowfullscreen',
    'allowpaymentrequest',
    'allowtransparency',
    'async',
    'autofocus',
    'autoplay',
    'checked',
    'compact',
    'controls',
    'declare',
    'default',
    'defaultchecked',
    'defaultmuted',
    'defaultselected',
    'defer',
    'disabled',
    'enabled',
    'formnovalidate',
    'hidden',
    'indeterminate',
    'inert',
    'ismap',
    'itemscope',
    'loop',
    'multiple',
    'muted',
    'nohref',
    'noresize',
    'noshade',
    'novalidate',
    'nowrap',
    'open',
    'pauseonexit',
    'readonly',
    'required',
    'reversed',
    'scoped',
    'seamless',
    'selected',
    'sortable',
    'truespeed',
    'typemustmatch',
    'visible'
]);

const amphtmlBooleanAttributes = new Set([
    '⚡',
    'amp',
    '⚡4ads',
    'amp4ads',
    '⚡4email',
    'amp4email',

    'amp-custom',
    'amp-boilerplate',
    'amp4ads-boilerplate',
    'amp4email-boilerplate',

    'allow-blocked-ranges',
    'amp-access-hide',
    'amp-access-template',
    'amp-keyframes',
    'animate',
    'arrows',
    'data-block-on-consent',
    'data-enable-refresh',
    'data-multi-size',
    'date-template',
    'disable-double-tap',
    'disable-session-states',
    'disableremoteplayback',
    'dots',
    'expand-single-section',
    'expanded',
    'fallback',
    'first',
    'fullscreen',
    'inline',
    'lightbox',
    'noaudio',
    'noautoplay',
    'noloading',
    'once',
    'open-after-clear',
    'open-after-select',
    'open-button',
    'placeholder',
    'preload',
    'reset-on-refresh',
    'reset-on-resize',
    'resizable',
    'rotate-to-fullscreen',
    'second',
    'standalone',
    'stereo',
    'submit-error',
    'submit-success',
    'submitting',
    'subscriptions-actions',
    'subscriptions-dialog'
]);

export default function collapseBooleanAttributes(tree, options, moduleOptions) {
    tree.match({attrs: true}, node => {
        for (let attrName of Object.keys(node.attrs)) {
            if (!node.tag) {
                continue;
            }

            if (node.tag.search('a-') === 0 && attrName === 'visible') {
                continue;
            }

            if (htmlBooleanAttributes.has(attrName)) {
                node.attrs[attrName] = true;
            }
            if (moduleOptions.amphtml && node.attrs[attrName] === '' && amphtmlBooleanAttributes.has(attrName)) {
                node.attrs[attrName] = true;
            }
        }

        return node;
    });

    return tree;
}
<|endoftext|>


<commit_before>/*!
 * parse-copyright <https://github.com/jonschlinkert/parse-copyright>
 *
 * Copyright (c) 2015 Jon Schlinkert, contributors.
 * Licensed under the MIT license.
 */

'use strict';

var regex = require('copyright-regex');

module.exports = function (str, options) {
  var res = [];
  var match;

  while (match = parse(str, options)) {
    str = str.replace(match.statement, '');
    res.push(match);
  }

  return res;
};

function parse(str, options) {
  var match = regex().exec(str);
  if (!match) { return null; }

  if (!isValid(match[0])) {
    return null;
  }

  if (options && options.original) {
    res.original = str;
  }

  var res = {};
  // 'Copyright (c) 2013-2015, 2016, Jon Schlinkert'
  if (match[0]) { res.statement = match[0]; }
  // 'Copyright'
  if (match[1]) { res.prefix = match[1]; }
  // '(c)'
  if (match[2]) { res.symbol = match[2]; }
  // '2013-2015, 2016, '
  if (match[3]) { res.dateRange = clean(match[3]); }
  // '2016'
  if (match[4]) { res.latest = match[4]; }
  // 'Jon Schlinkert'
  if (match[5]) { res.author = clean(match[5]); }
  return res;
}

function clean(str) {
  return str.replace(/^\W*|\W*$/g, '');
}

function isValid(str) {
  if (!/(?:(?:19|20)[0-9]{2})/.test(str)) {
    return false;
  }
  return true;
}
<commit_msg>adds `first` property<commit_after>/*!
 * parse-copyright <https://github.com/jonschlinkert/parse-copyright>
 *
 * Copyright (c) 2015, Jon Schlinkert.
 * Licensed under the MIT License.
 */

'use strict';

var regex = require('copyright-regex');

module.exports = function (str, options) {
  var res = [];
  var match;

  while (match = parse(str, options)) {
    str = str.replace(match.statement, '');
    res.push(match);
  }

  return res;
};

function parse(str, options) {
  var match = regex().exec(str);
  if (!match) { return null; }

  if (!isValid(match[0])) {
    return null;
  }

  if (options && options.original) {
    res.original = str;
  }

  var res = {};
  // 'Copyright (c) 2013-2015, 2016, Jon Schlinkert'
  if (match[0]) { res.statement = match[0]; }
  // 'Copyright'
  if (match[1]) { res.prefix = match[1]; }
  // '(c)'
  if (match[2]) { res.symbol = match[2]; }
  // '2013-2015, 2016, '
  if (match[3]) { res.dateRange = clean(match[3]); }
  if (match[3]) { res.first = first(res.dateRange); }
  // '2016'
  if (match[4]) { res.latest = match[4]; }
  // 'Jon Schlinkert'
  if (match[5]) { res.author = clean(match[5]); }
  return res;
}

function first(str) {
  var years = str.split(/\W/);
  if (years && years.length && /^\d+$/.test(years[0])) {
    return years[0];
  }
  return null;
}

function clean(str) {
  return str.replace(/^\W*|\W*$/g, '');
}

function isValid(str) {
  if (!/(?:(?:19|20)[0-9]{2})/.test(str)) {
    return false;
  }
  return true;
}<|endoftext|>


<commit_before>const BrowserWindow = require('electron').remote.BrowserWindow
const ipcRenderer = require('electron').ipcRenderer
const path = require('path')

const invisMsgBtn = document.getElementById('invis-msg')
const invisReply = document.getElementById('invis-reply')

invisMsgBtn.addEventListener('click', function (clickEvent) {
  const windowID = BrowserWindow.getFocusedWindow().id
  const invisPath = 'file://' + path.join(__dirname, 'sections/communication/invisible.html')
  let win = new BrowserWindow({ width: 400, height: 400, show: false })
  win.loadURL(invisPath)

  win.webContents.on('did-finish-load', function (clickEvent) {
    const input = 100
    win.webContents.send('compute-factorial', input, windowID)
  })
})

ipcRenderer.on('factorial-computed', function (event, input, output) {
  const message = `The factorial of ${input} is ${output}`
  invisReply.textContent = message
})
<commit_msg>remove unused var<commit_after>const BrowserWindow = require('electron').remote.BrowserWindow
const ipcRenderer = require('electron').ipcRenderer
const path = require('path')

const invisMsgBtn = document.getElementById('invis-msg')
const invisReply = document.getElementById('invis-reply')

invisMsgBtn.addEventListener('click', function (clickEvent) {
  const windowID = BrowserWindow.getFocusedWindow().id
  const invisPath = 'file://' + path.join(__dirname, 'sections/communication/invisible.html')
  let win = new BrowserWindow({ width: 400, height: 400, show: false })
  win.loadURL(invisPath)

  win.webContents.on('did-finish-load', function () {
    const input = 100
    win.webContents.send('compute-factorial', input, windowID)
  })
})

ipcRenderer.on('factorial-computed', function (event, input, output) {
  const message = `The factorial of ${input} is ${output}`
  invisReply.textContent = message
})
<|endoftext|>


<commit_before>/**
 * Module dependencies
 */

var util = require('util');
var makeECMAScriptCompatible = require('./makeECMAScriptCompatible');

/**
 * sails-generate-directive
 *
 * Usage:
 * `sails generate directive`
 *
 * @description Generates an Angular directive within a Sails project.
 * @help See http://links.sailsjs.org/docs/generators
 */

module.exports = {

  before: function (scope, cb) {

    if (!scope.args[0]) {
      return cb( new Error('Please provide the name for this directive using HTML (dash, NOT camel case) syntax; e.g. "foo-bar-baz").') );
    }

    // The first command-line argument will be used as the dash-delimited
    // (or "htmlized") directive name
    scope.htmlizedDirectiveName = scope.args[0];

    // Calculate the camel-cased version
    scope.camelCasedDirectiveName = makeECMAScriptCompatible(scope.htmlizedDirectiveName);

    // Decide the output filename for use in targets below:
    scope.filename = scope.htmlizedDirectiveName + '.directive.js';

    // Path to directives dir within the project
    // (set using --directory or --directives-directory)
    scope.directory = scope.directory||scope['directives-directory']||'assets/js/directives';

    scope.htmlExample = (function build_html_example(htmlizedDirectiveName) {
      return util.format('<%s></%s>', htmlizedDirectiveName, htmlizedDirectiveName);
    })(scope.htmlizedDirectiveName);

    // If a module name was not provided as `--module`, default to 'App'.
    scope.module = scope.module || 'App';

    cb();
  },

  /**
   * The files/folders to generate.
   * @type {Object}
   */

  targets: {

    './:directory/:filename': { template: 'new-directive.gen' },

  },

  /**
   * The absolute path to the `templates` for this generator
   * (for use with the `template` helper)
   *
   * @type {String}
   */
  templatesDirectory: require('path').resolve(__dirname)
};
<commit_msg>dont allow --directory flag (to avoid potentailcollisions when called from other generators)<commit_after>/**
 * Module dependencies
 */

var util = require('util');
var makeECMAScriptCompatible = require('./makeECMAScriptCompatible');

/**
 * sails-generate-directive
 *
 * Usage:
 * `sails generate directive`
 *
 * @description Generates an Angular directive within a Sails project.
 * @help See http://links.sailsjs.org/docs/generators
 */

module.exports = {

  before: function (scope, cb) {

    if (!scope.args[0]) {
      return cb( new Error('Please provide the name for this directive using HTML (dash, NOT camel case) syntax; e.g. "foo-bar-baz").') );
    }

    // The first command-line argument will be used as the dash-delimited
    // (or "htmlized") directive name
    scope.htmlizedDirectiveName = scope.args[0];

    // Calculate the camel-cased version
    scope.camelCasedDirectiveName = makeECMAScriptCompatible(scope.htmlizedDirectiveName);

    // Decide the output filename for use in targets below:
    scope.filename = scope.htmlizedDirectiveName + '.directive.js';

    // Path to directives dir within the project
    // (set using --directives-directory)
    scope.directivesDirectory = scope['directives-directory']||'assets/js/directives';

    scope.htmlExample = (function build_html_example(htmlizedDirectiveName) {
      return util.format('<%s></%s>', htmlizedDirectiveName, htmlizedDirectiveName);
    })(scope.htmlizedDirectiveName);

    // If a module name was not provided as `--module`, default to 'App'.
    scope.module = scope.module || 'App';

    cb();
  },

  /**
   * The files/folders to generate.
   * @type {Object}
   */

  targets: {

    './:directivesDirectory/:filename': { template: 'new-directive.gen' },

  },

  /**
   * The absolute path to the `templates` for this generator
   * (for use with the `template` helper)
   *
   * @type {String}
   */
  templatesDirectory: require('path').resolve(__dirname)
};
<|endoftext|>


<commit_before>function diagramEditorCntrl($scope){
	var api = $scope.$parent.api;
	api.editedObject = {}
	$scope.newObject = {
		"name" : "",
		// "id": null,
		// "type" : null,
		"inputs" : [],
		"outputs" : []
	}
	$scope.portarrays = [];

	api.componentEditDetail = function() {
		// console.log("Component Detail")
		var selection = d3.selectAll(".selected-object");
		var count = selection[0].length
		if (count == 0) {
			console.log("No object selected!")
		} else if (count > 1) {
			console.log("Too many objects selected!")
		} else {
			d3.selectAll("#componentEdit").style("display", "block");

			// console.log(selection[0][0])
			var object = selection[0][0]
			var selected = object.getElementsByTagName("g");
			// console.log(object.__data__)
			$scope.editedObject = object.__data__;
			$scope.portarrays = [ {
				'array' : $scope.editedObject.inputs,
				'name' : 'Inputs'
			}, {
				'array' : $scope.editedObject.outputs,
				'name' : 'Outputs'
			} ]
		}

	}

	$scope.componentRemovePort = function(object, group, port) {
		console.log("ComponentEditRemovePort")
		// console.log(object, group, port);
		var portGroup = (group == 'Inputs' ? object.inputs : object.outputs)
		// console.log(portGroup, port);
		var index = portGroup.indexOf(port);
		if (index > -1) {
			portGroup.splice(index, 1);
		} else {
			console.log("Remove port error: port does not exist")
		}
		// componentEdit redraw
		// api.redraw();
	}

	$scope.componentAddPort = function(object, group) {
		//console.log("ComponentEditAddPort")
		//console.log(group, object)
		var portGroup = (group == 'Inputs' ? object.inputs : object.outputs)

		portGroup.unshift({
			"name" : ""
		});
		// componentEdit redraw
		// api.redraw();
	}

	$scope.componentEditSubmit = function() {
		api.redraw();
		//console.log("Submit")
		//console.log($scope.editedObject.inputs)
		// d3.selectAll("#componentEdit").style("display", "none");
	}

	$scope.componentEditCancel = function() {
		//console.log("Cancel")
		d3.selectAll("#componentEdit").style("display", "none");
	}

	api.objectDelete = function() {
		// All selected objects
		var objects = d3.selectAll(".selected-object")[0];
		var links = d3.selectAll(".selected-link")[0];
		//console.log("Selected objects", objects);
		//console.log("Selected links", links.length, links);
		for (i = 0; i < objects.length; i++) {
			var obj = objects[i].__data__;
			// console.log(obj)
			// console.log("Nodes: ", api.nodes)
			// console.log("Nets: ", api.nets)
			// console.log("Object check")
			// For all nodes in scope
			for (var i = 0; i < api.nodes.length; i++) {
				// console.log(api.nodes[i].name)
				// Delete matching objects
				if (api.nodes[i].name == obj.name) {
					api.nodes.splice(i, 1);
				}
			}
			//console.log("Nets", obj.id)
			// For all nets in scope
			for (var j = 0; j < api.nets.length; j++) {
				// For all links
				var net = api.nets[j];
				for (var l = 0; l < net.targets.length; l++) {
					// Delete all links from deleted object
					var target = net.targets[l];
					if ((target.id == obj.id) | (net.source.id == obj.id)) {
						// console.log("Net: ", target, net.source)
						var removed = api.nets.splice(j, 1);
						j--;
						break;
					}
				}// for net targets
			}// for scope nets
		}// for selected objects

		//console.log("Link check")
		// For all selected links
		for (var m = 0; m < links.length; m++) {
			var net = links[m].__data__.net;
			var index = api.nets.indexOf(net);
			// Delete all selected links
			if (index > -1) {
				api.nets.splice(index, 1);
			}
		}
		// console.log(api.nets)
		api.redraw();
		return;
	}

	function getComponentID(){
		var max = -1;
		for (var i = 0; i< api.nodes.length; i++)
		{
			if (api.nodes[i].id > max)
			{
				max = api.nodes[i].id;
			}
		}
		//console.log("Maximum: ", max);
		return max;
	}

	api.componentAdd = function() {
		d3.selectAll("#componentAdd").style("display", "block");
		var id = getComponentID();
		$scope.newObject = {
			"name" : "",
			"id": id,
			"type" : "",
			"inputs" : [],
			"outputs" : []
		}
		$scope.portarrays = [ {
			'array' : $scope.newObject.inputs,
			'name' : 'Inputs'
		}, {
			'array' : $scope.newObject.outputs,
			'name' : 'Outputs'
		} ]
	}

	$scope.componentAddSubmit = function() {
		console.log("Submit")
		console.log("Before: ", api.nodes)
		api.nodes.push($scope.newObject);
		console.log("After: ", api.nodes)

		api.redraw();

		// d3.selectAll("#componentAdd").style("display", "none");
	}

	$scope.componentAddCancel = function() {
		console.log("Cancel")
		d3.selectAll("#componentAdd").style("display", "none");
	}

	$scope.origin = {
		"component" : {},
		"portElm" : null,
		"port" : {}
	};
	$scope.destination = {
		"component" : {},
		"port" : {}
	};
	$scope.linkstatus = "none";

	function drawDashedLine2port(elm, mousePossition){
		//console.log(mousePossition); $scope.origin.getPos()
		var line = api.diagramSvg.selectAll('.routing-help-line');
		if(line.empty()){
			line = api.diagramSvg.append("svg:path")
				       .classed({"routing-help-line": true})
		}
		line
	        .style("stroke-dasharray", ("3, 3"))
	        .attr("d", 'M '+ [0,0] + "L " + mousePossition );
	}

	api.portClick = function(d, elm) {
		//console.log("portClick data", d);
		//console.log("Link status", $scope.linkstatus)
		switch ($scope.linkstatus) {
		case "none":
			//console.log("Setting origin")
			$scope.origin.port = d;
			$scope.linkstatus = "origincomp";
			break;
		case "destination":
			//console.log("Setting destination")
			$scope.destination.port = d;
			$scope.linkstatus = "destinationcomp";
			break;
		}
		//console.log("Link status", $scope.linkstatus)
		//console.log("Origin", $scope.origin)
		//console.log("Destination", $scope.destination)
	}

	api.compClick = function(d) {
		// console.log("Component Click data", d);
		// console.log("Link status", $scope.linkstatus)
		switch ($scope.linkstatus) {
		case "origincomp":
			// console.log("Setting origin component")
			$scope.origin.component = d;
			$scope.linkstatus = "destination";
			api.onMouseroverDiagram = drawDashedLine2port;
			break;
		case "destinationcomp":
			// console.log("Setting destination component")
			$scope.destination.component = d;
			$scope.linkstatus = "link";
			break;
		default:
			// console.log("Breaking")
			break;
		}

		// console.log("Link status", $scope.linkstatus)
		// console.log("Origin", $scope.origin)
		// console.log("Destination", $scope.destination)

		if ($scope.linkstatus == "link") {
			// console.log("Linking");
			var originportinfo = $scope.getPortIndexByName(
					$scope.origin.port.name, $scope.origin.component)
			var destinationportinfo = $scope.getPortIndexByName(
					$scope.destination.port.name, $scope.destination.component)
			var net = $scope.makeNet(originportinfo, destinationportinfo,
					$scope.origin.component, $scope.destination.component);

			// console.log("Net to be added: ", net)
			if (net != "") {
				//console.log("Adding net", net)
				api.nets.push(net);
			}
			api.resetLinkingState();
			api.redraw();

		}// if scopestatus link

	}

	$scope.makeNet = function(originport, destinationport, origincomponent,
			destinationcomponent) {
		var origin = {
			"portIndex" : originport[0],
			"id" : origincomponent.id
		}
		var destination = {
			"portIndex" : destinationport[0],
			"id" : destinationcomponent.id
		}
		if (originport[1] == destinationport[1]) {
			api.msg.error("Can't connect matching port groups",
					"QuickLink Erorr")
			return "";
		} else if ((originport[1] == null | destinationport[1] == null)) {
			api.msg.error("Can't connect link port name corrupted",
					"QuickLink Erorr")
			return "";
		}
		// TODO check whether net already exists?
		if (originport[1] == "inputs") {

			net = {
				"targets" : [ origin ],
				"source" : destination
			}
		}// if originport inputs
		else if (originport[1] == "outputs") {
			net = {
				"targets" : [ destination ],
				"source" : origin
			}
		}
		return net;
	}

	$scope.getPortIndexByName = function (name, component)
	{
		for (var i = 0; i < component.inputs.length;i++)
		{
			if (name == component.inputs[i].name)
			{
				//console.log("Match input", name, component.inputs[i].name)
				return [i, "inputs"];
			}
		}

		for (var j = 0; j < component.outputs.length;j++)
		{
			if (name == component.outputs[j].name)
			{
				//console.log("Match output", name, component.outputs[i].name)
				return [j, "outputs"];
			}
		}
		return [null, null];
	}

	api.resetLinkingState = function() {
		$scope.linkstatus = "none";
	}
}<commit_msg>id default value<commit_after>function diagramEditorCntrl($scope){
	var api = $scope.$parent.api;
	api.editedObject = {}
	$scope.newObject = {
		"name" : "",
		// "id": null,
		// "type" : null,
		"inputs" : [],
		"outputs" : []
	}
	$scope.portarrays = [];

	api.componentEditDetail = function() {
		// console.log("Component Detail")
		var selection = d3.selectAll(".selected-object");
		var count = selection[0].length
		if (count == 0) {
			console.log("No object selected!")
		} else if (count > 1) {
			console.log("Too many objects selected!")
		} else {
			d3.selectAll("#componentEdit").style("display", "block");

			// console.log(selection[0][0])
			var object = selection[0][0]
			var selected = object.getElementsByTagName("g");
			// console.log(object.__data__)
			$scope.editedObject = object.__data__;
			$scope.portarrays = [ {
				'array' : $scope.editedObject.inputs,
				'name' : 'Inputs'
			}, {
				'array' : $scope.editedObject.outputs,
				'name' : 'Outputs'
			} ]
		}

	}

	$scope.componentRemovePort = function(object, group, port) {
		console.log("ComponentEditRemovePort")
		// console.log(object, group, port);
		var portGroup = (group == 'Inputs' ? object.inputs : object.outputs)
		// console.log(portGroup, port);
		var index = portGroup.indexOf(port);
		if (index > -1) {
			portGroup.splice(index, 1);
		} else {
			console.log("Remove port error: port does not exist")
		}
		// componentEdit redraw
		// api.redraw();
	}

	$scope.componentAddPort = function(object, group) {
		//console.log("ComponentEditAddPort")
		//console.log(group, object)
		var portGroup = (group == 'Inputs' ? object.inputs : object.outputs)

		portGroup.unshift({
			"name" : ""
		});
		// componentEdit redraw
		// api.redraw();
	}

	$scope.componentEditSubmit = function() {
		api.redraw();
		//console.log("Submit")
		//console.log($scope.editedObject.inputs)
		// d3.selectAll("#componentEdit").style("display", "none");
	}

	$scope.componentEditCancel = function() {
		//console.log("Cancel")
		d3.selectAll("#componentEdit").style("display", "none");
	}

	api.objectDelete = function() {
		// All selected objects
		var objects = d3.selectAll(".selected-object")[0];
		var links = d3.selectAll(".selected-link")[0];
		//console.log("Selected objects", objects);
		//console.log("Selected links", links.length, links);
		for (i = 0; i < objects.length; i++) {
			var obj = objects[i].__data__;
			// console.log(obj)
			// console.log("Nodes: ", api.nodes)
			// console.log("Nets: ", api.nets)
			// console.log("Object check")
			// For all nodes in scope
			for (var i = 0; i < api.nodes.length; i++) {
				// console.log(api.nodes[i].name)
				// Delete matching objects
				if (api.nodes[i].name == obj.name) {
					api.nodes.splice(i, 1);
				}
			}
			//console.log("Nets", obj.id)
			// For all nets in scope
			for (var j = 0; j < api.nets.length; j++) {
				// For all links
				var net = api.nets[j];
				for (var l = 0; l < net.targets.length; l++) {
					// Delete all links from deleted object
					var target = net.targets[l];
					if ((target.id == obj.id) | (net.source.id == obj.id)) {
						// console.log("Net: ", target, net.source)
						var removed = api.nets.splice(j, 1);
						j--;
						break;
					}
				}// for net targets
			}// for scope nets
		}// for selected objects

		//console.log("Link check")
		// For all selected links
		for (var m = 0; m < links.length; m++) {
			var net = links[m].__data__.net;
			var index = api.nets.indexOf(net);
			// Delete all selected links
			if (index > -1) {
				api.nets.splice(index, 1);
			}
		}
		// console.log(api.nets)
		api.redraw();
		return;
	}

	function getComponentID(){
		var max = -1;
		for (var i = 0; i< api.nodes.length; i++)
		{
			if (api.nodes[i].id > max)
			{
				max = api.nodes[i].id;
			}
		}
		//console.log("Maximum: ", max);
		return max;
	}

	api.componentAdd = function() {
		d3.selectAll("#componentAdd").style("display", "block");
		var id = "";
		id = getComponentID();
		$scope.newObject = {
			"name" : "",
			"id": id,
			"type" : "",
			"inputs" : [],
			"outputs" : []
		}
		$scope.portarrays = [ {
			'array' : $scope.newObject.inputs,
			'name' : 'Inputs'
		}, {
			'array' : $scope.newObject.outputs,
			'name' : 'Outputs'
		} ]
	}

	$scope.componentAddSubmit = function() {
		console.log("Submit")
		console.log("Before: ", api.nodes)
		api.nodes.push($scope.newObject);
		console.log("After: ", api.nodes)

		api.redraw();

		// d3.selectAll("#componentAdd").style("display", "none");
	}

	$scope.componentAddCancel = function() {
		console.log("Cancel")
		d3.selectAll("#componentAdd").style("display", "none");
	}

	$scope.origin = {
		"component" : {},
		"portElm" : null,
		"port" : {}
	};
	$scope.destination = {
		"component" : {},
		"port" : {}
	};
	$scope.linkstatus = "none";

	function drawDashedLine2port(elm, mousePossition){
		//console.log(mousePossition); $scope.origin.getPos()
		var line = api.diagramSvg.selectAll('.routing-help-line');
		if(line.empty()){
			line = api.diagramSvg.append("svg:path")
				       .classed({"routing-help-line": true})
		}
		line
	        .style("stroke-dasharray", ("3, 3"))
	        .attr("d", 'M '+ [0,0] + "L " + mousePossition );
	}

	api.portClick = function(d, elm) {
		//console.log("portClick data", d);
		//console.log("Link status", $scope.linkstatus)
		switch ($scope.linkstatus) {
		case "none":
			//console.log("Setting origin")
			$scope.origin.port = d;
			$scope.linkstatus = "origincomp";
			break;
		case "destination":
			//console.log("Setting destination")
			$scope.destination.port = d;
			$scope.linkstatus = "destinationcomp";
			break;
		}
		//console.log("Link status", $scope.linkstatus)
		//console.log("Origin", $scope.origin)
		//console.log("Destination", $scope.destination)
	}

	api.compClick = function(d) {
		// console.log("Component Click data", d);
		// console.log("Link status", $scope.linkstatus)
		switch ($scope.linkstatus) {
		case "origincomp":
			// console.log("Setting origin component")
			$scope.origin.component = d;
			$scope.linkstatus = "destination";
			api.onMouseroverDiagram = drawDashedLine2port;
			break;
		case "destinationcomp":
			// console.log("Setting destination component")
			$scope.destination.component = d;
			$scope.linkstatus = "link";
			break;
		default:
			// console.log("Breaking")
			break;
		}

		// console.log("Link status", $scope.linkstatus)
		// console.log("Origin", $scope.origin)
		// console.log("Destination", $scope.destination)

		if ($scope.linkstatus == "link") {
			// console.log("Linking");
			var originportinfo = $scope.getPortIndexByName(
					$scope.origin.port.name, $scope.origin.component)
			var destinationportinfo = $scope.getPortIndexByName(
					$scope.destination.port.name, $scope.destination.component)
			var net = $scope.makeNet(originportinfo, destinationportinfo,
					$scope.origin.component, $scope.destination.component);

			// console.log("Net to be added: ", net)
			if (net != "") {
				//console.log("Adding net", net)
				api.nets.push(net);
			}
			api.resetLinkingState();
			api.redraw();

		}// if scopestatus link

	}

	$scope.makeNet = function(originport, destinationport, origincomponent,
			destinationcomponent) {
		var origin = {
			"portIndex" : originport[0],
			"id" : origincomponent.id
		}
		var destination = {
			"portIndex" : destinationport[0],
			"id" : destinationcomponent.id
		}
		if (originport[1] == destinationport[1]) {
			api.msg.error("Can't connect matching port groups",
					"QuickLink Erorr")
			return "";
		} else if ((originport[1] == null | destinationport[1] == null)) {
			api.msg.error("Can't connect link port name corrupted",
					"QuickLink Erorr")
			return "";
		}
		// TODO check whether net already exists?
		if (originport[1] == "inputs") {

			net = {
				"targets" : [ origin ],
				"source" : destination
			}
		}// if originport inputs
		else if (originport[1] == "outputs") {
			net = {
				"targets" : [ destination ],
				"source" : origin
			}
		}
		return net;
	}

	$scope.getPortIndexByName = function (name, component)
	{
		for (var i = 0; i < component.inputs.length;i++)
		{
			if (name == component.inputs[i].name)
			{
				//console.log("Match input", name, component.inputs[i].name)
				return [i, "inputs"];
			}
		}

		for (var j = 0; j < component.outputs.length;j++)
		{
			if (name == component.outputs[j].name)
			{
				//console.log("Match output", name, component.outputs[i].name)
				return [j, "outputs"];
			}
		}
		return [null, null];
	}

	api.resetLinkingState = function() {
		$scope.linkstatus = "none";
	}
}<|endoftext|>


<commit_before>'use strict';
var pkg = require('./package');
var gutil = require('gulp-util');
var through = require('through2');
var path = require('path');
var File = require('vinyl');

// consts
module.exports = function(out, options) {

  options = options || {};

  var fileList = [];

  return through.obj(function(file, enc, cb) {

    if (file.isNull()) {
      cb(null, file);
      return;
    }

    if (file.isStream()) {
      cb(new gutil.PluginError(pkg.name, 'Streams not supported'));
      return;
    }

    var filePath;
    if (options.absolute) {
      filePath = path.normalize(file.path);
    } else if (options.flatten) {
      filePath = path.basename(file.path);
    } else {
      filePath = path.relative(file.cwd, file.path);
    }
    if (options.removeExtensions) {
      var extension = path.extname(filePath);
      if (extension.length) {
        filePath = filePath.slice(0, -extension.length);
      }
    }
    filePath = filePath.replace(/\\/g, '/');

    if(options.destRowTemplate) {
      fileList.push(options.destRowTemplate.replace('@filePath@', filePath));
    } else {
      fileList.push(filePath);
    }

    cb();
  }, function(cb) {
    var buffer = (options.destRowTemplate) ? new Buffer(fileList.join('\r\n')) : new Buffer(JSON.stringify(fileList, null, '  '));

    var fileListFile = new File({
      path: out,
      contents: buffer
    });

    this.push(fileListFile);
    cb();
  });
};
<commit_msg>Remove hardcoded newlines in template option<commit_after>'use strict';
var pkg = require('./package');
var gutil = require('gulp-util');
var through = require('through2');
var path = require('path');
var File = require('vinyl');

// consts
module.exports = function(out, options) {

  options = options || {};

  var fileList = [];

  return through.obj(function(file, enc, cb) {

    if (file.isNull()) {
      cb(null, file);
      return;
    }

    if (file.isStream()) {
      cb(new gutil.PluginError(pkg.name, 'Streams not supported'));
      return;
    }

    var filePath;
    if (options.absolute) {
      filePath = path.normalize(file.path);
    } else if (options.flatten) {
      filePath = path.basename(file.path);
    } else {
      filePath = path.relative(file.cwd, file.path);
    }
    if (options.removeExtensions) {
      var extension = path.extname(filePath);
      if (extension.length) {
        filePath = filePath.slice(0, -extension.length);
      }
    }
    filePath = filePath.replace(/\\/g, '/');

    if(options.destRowTemplate) {
      fileList.push(options.destRowTemplate.replace('@filePath@', filePath));
    } else {
      fileList.push(filePath);
    }

    cb();
  }, function(cb) {
    var buffer = (options.destRowTemplate) ? new Buffer(fileList.join('')) : new Buffer(JSON.stringify(fileList, null, '  '));

    var fileListFile = new File({
      path: out,
      contents: buffer
    });

    this.push(fileListFile);
    cb();
  });
};
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// VERSION 1.1.0

this.TabCenter = {
	id: 'tabcentertest1@mozilla.com',

	observe: function(aSubject, aTopic, aData) {
		if(Prefs.slimChrome) {
			this.listen();
		} else {
			this.unlisten();
		}
	},

	attrWatcher: function() {
		if(self.slimChrome) {
			slimChrome.delayMove();
		}
	},

	onEnabled: function(addon) {
		if(addon.id == this.id) { this.enable(); }
	},

	onDisabled: function(addon) {
		if(addon.id == this.id) {
			this.disable();

			// Make sure Slim Chrome is re-enabled (if necessary) after having been disabled to allow Tab Center to unload properly.
			toggleSlimChrome();
		}
	},

	onDisabling: function(addon) {
		if(addon.id == this.id) {
			// Tab Center has trouble deinitializing because it can't find the nav-bar in the toolbox.
			// So we disable Slim Chrome to put it back, then re-enable it later once Tab Center is fully unloaded.
			// (This can probably be safely removed once Tab Center is updated.)
			Modules.unload('slimChrome');
		}
	},

	listen: function() {
		AddonManager.addAddonListener(this);
		AddonManager.getAddonByID(this.id, (addon) => {
			if(addon && addon.isActive) { this.enable(); }
		});
	},

	unlisten: function() {
		AddonManager.removeAddonListener(this);
		this.disable();
	},

	enable: function() {
		// Don't use an external sheet for this, it's just better to load this code per-window as necessary.
		let sscode = '\
			@namespace url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul);\n\
			@-moz-document url("'+document.baseURI+'") {\n\
				window['+objName+'_UUID="'+_UUID+'"] #verticaltabs-box {\n\
					transition: box-shadow 150ms ease-out 300ms, width 150ms ease-out 300ms, z-index 0s ease-out 400ms;\n\
				}\n\
				window['+objName+'_UUID="'+_UUID+'"] #verticaltabs-box:hover {\n\
					z-index: 410;\n\
				}\n\
			}';
		Styles.load('tabCenter_'+_UUID, sscode, true);

		Watchers.addAttributeWatcher(document.documentElement, 'tabspinned', this, false, false);

		if(self.slimChrome) {
			slimChrome.delayMove();
		}
	},

	disable: function() {
		Styles.unload('tabCenter_'+_UUID);
		Watchers.removeAttributeWatcher(document.documentElement, 'tabspinned', this, false, false);

		if(!UNLOADED && Prefs.slimChrome && self.slimChrome) {
			slimChrome.delayMove();
		}
	}
};

Modules.LOADMODULE = function() {
	Prefs.listen('slimChrome', TabCenter);

	if(Prefs.slimChrome) {
		TabCenter.listen();
	}
};

Modules.UNLOADMODULE = function() {
	TabCenter.unlisten();

	Prefs.unlisten('slimChrome', TabCenter);
};
<commit_msg>update some Tab Center compatibility code<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// VERSION 1.1.1

this.TabCenter = {
	id: 'tabcentertest1@mozilla.com',

	observe: function(aSubject, aTopic, aData) {
		if(Prefs.slimChrome) {
			this.listen();
		} else {
			this.unlisten();
		}
	},

	attrWatcher: function() {
		if(self.slimChrome) {
			slimChrome.delayMove();
		}
	},

	onEnabled: function(addon) {
		if(addon.id == this.id) { this.enable(); }
	},

	onDisabled: function(addon) {
		if(addon.id == this.id) {
			this.disable();

			// Make sure Slim Chrome is re-enabled (if necessary) after having been disabled to allow Tab Center to unload properly.
			toggleSlimChrome();
		}
	},

	onDisabling: function(addon) {
		if(addon.id == this.id) {
			// Tab Center has trouble deinitializing because it can't find the nav-bar in the toolbox.
			// So we disable Slim Chrome to put it back, then re-enable it later once Tab Center is fully unloaded.
			// (This can probably be safely removed once Tab Center is updated.)
			Modules.unload('slimChrome');
		}
	},

	listen: function() {
		AddonManager.addAddonListener(this);
		AddonManager.getAddonByID(this.id, (addon) => {
			if(addon && addon.isActive) { this.enable(); }
		});
	},

	unlisten: function() {
		AddonManager.removeAddonListener(this);
		this.disable();
	},

	enable: function() {
		// The Sky Lights shouldn't be visible above the veritcal tabs strip.
		// Don't use an external sheet for this, it's just better to load this code per-window as necessary.
		let sscode = '\
			@namespace url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul);\n\
			@-moz-document url("'+document.baseURI+'") {\n\
				window['+objName+'_UUID="'+_UUID+'"]:not([tabspinned="true"]) #verticaltabs-box {\n\
					transition: box-shadow 150ms, width 150ms, z-index 0s ease-out 400ms;\n\
				}\n\
				window['+objName+'_UUID="'+_UUID+'"] #verticaltabs-box:hover {\n\
					z-index: 410;\n\
				}\n\
			}';
		Styles.load('tabCenter_'+_UUID, sscode, true);

		Watchers.addAttributeWatcher(document.documentElement, 'tabspinned', this, false, false);

		if(self.slimChrome) {
			slimChrome.delayMove();
		}
	},

	disable: function() {
		Styles.unload('tabCenter_'+_UUID);
		Watchers.removeAttributeWatcher(document.documentElement, 'tabspinned', this, false, false);

		if(!UNLOADED && Prefs.slimChrome && self.slimChrome) {
			slimChrome.delayMove();
		}
	}
};

Modules.LOADMODULE = function() {
	Prefs.listen('slimChrome', TabCenter);

	if(Prefs.slimChrome) {
		TabCenter.listen();
	}
};

Modules.UNLOADMODULE = function() {
	TabCenter.unlisten();

	Prefs.unlisten('slimChrome', TabCenter);
};
<|endoftext|>


<commit_before>moduleAid.VERSION = '1.0.0';

/* This is easier than adding a whole stylesheet just for the button */
moduleAid.LOADMODULE = function() {
	var sscode = '/*FindBar Tweak CSS declarations of variable values*/\n';
	sscode += '@namespace url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul);\n';
	sscode += '@-moz-document url("chrome://global/content/customizeToolbar.xul") {\n';
	sscode += '	#findbartweak-button { list-style-image: url("chrome://findbartweak/skin/button.png") !important; }\n';
	sscode += '}';

	styleAid.load('customizeButton', sscode, true);
};

moduleAid.UNLOADMODULE = function() {
	styleAid.unload('customizeButton');
};
<commit_msg>bugfix button showing default toolbar.png<commit_after>moduleAid.VERSION = '1.0.1';

/* This is easier than adding a whole stylesheet just for the button */
moduleAid.LOADMODULE = function() {
	var sscode = '/*FindBar Tweak CSS declarations of variable values*/\n';
	sscode += '@namespace url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul);\n';
	sscode += '@-moz-document url("chrome://browser/content/browser.xul"), url("chrome://global/content/customizeToolbar.xul") {\n';
	sscode += '	#findbartweak-button { list-style-image: url("chrome://findbartweak/skin/button.png") !important; }\n';
	sscode += '}';

	styleAid.load('customizeButton', sscode, true);
};

moduleAid.UNLOADMODULE = function() {
	styleAid.unload('customizeButton');
};
<|endoftext|>


<commit_before>function appendOp (url, op) {
  var parts = url.split('/')

  if (url[url.length - 1] === '/') {
    parts[parts.length - 1] = op
  } else {
    parts[parts.length - 1] = op + parts[parts.length - 1]
  }

  return parts.join('/')
}

var FormatValues = ['png', 'jpeg']

exports.format = function (url, type) {
  if (FormatValues.indexOf(type) === -1) {
    throw new TypeError('Format must be one of ' + FormatValues)
  }

  return appendOp(url, '-/format/' + type + '/')
}

var QualityValues = ['normal', 'better', 'best', 'lighter', 'lightest']

exports.quality = function (url, value) {
  if (QualityValues.indexOf(value) === -1) {
    throw new TypeError('Quality must be one of ' + QualityValues)
  }

  return appendOp(url, '-/quality/' + value + '/')
}

var ProgressiveValues = ['yes', 'no']

exports.progressive = function (url, value) {
  if (Object.prototype.toString.call(value) === '[object Boolean]') {
    value = value ? 'yes' : 'no'
  }

  if (ProgressiveValues.indexOf(value) === -1) {
    throw new TypeError('Value must be one of ' + ProgressiveValues)
  }

  return appendOp(url, '-/progressive/' + value + '/')
}

var PreviewRegex = /^[0-9]+x[0-9]+$/

exports.preview = function (url, dims) {
  if (!PreviewRegex.test(dims)) {
    throw new TypeError('Invalid dimensions format, expected format example: 200x200')
  }

  return appendOp(url, '-/preview/' + dims + '/')
}

var ResizeRegex = /^([0-9]+x)|([0-9]+x[0-9]+)|(x[0-9]+)$/

exports.resize = function (url, dims) {
  if (!ResizeRegex.test(dims)) {
    throw new TypeError('Invalid dimensions format, expected format examples: 200x200, x200, 200x')
  }

  return appendOp(url, '-/resize/' + dims + '/')
}

var CropDimsRegex = /^[0-9]+x[0-9]+$/
var CropCoordsRegex = /^([0-9]+,[0-9])|center+$/

exports.crop = function (url, dims, coords) {
  if (!CropDimsRegex.test(dims)) {
    throw new TypeError('Invalid dimensions format, expected format example: 200x200')
  }

  if (coords) {
    if (!CropCoordsRegex.test(coords)) {
      throw new TypeError('Invalid coordinates format, expected format examples: 1400,1800, center')
    }

    return appendOp(url, '-/crop/' + dims + '/' + encodeURIComponent(coords) + '/')
  }

  return appendOp(url, '-/crop/' + dims + '/')
}

var ScaleCropDimsRegex = /^[0-9]+x[0-9]+$/

exports.scaleCrop = function (url, dims, center) {
  if (!ScaleCropDimsRegex.test(dims)) {
    throw new TypeError('Invalid dimensions format, expected format example: 200x200')
  }

  return appendOp(url, '-/scale_crop/' + dims + '/' + (center ? 'center/' : ''))
}

var StretchValues = ['on', 'off', 'fill']

exports.stretch = function (url, value) {
  if (StretchValues.indexOf(value) === -1) {
    throw new TypeError('Stretch must be one of ' + StretchValues)
  }

  return appendOp(url, '-/stretch/' + value + '/')
}

var SetFillRegex = /^[a-f0-9]{6}$/

exports.setFill = function (url, color) {
  if (!SetFillRegex.test(color)) {
    throw new TypeError('Color must be in hexadecimal notation')
  }

  return appendOp(url, '-/setfill/' + color + '/')
}

var AutoRotateValues = ['yes', 'no']

exports.autoRotate = function (url, value) {
  if (Object.prototype.toString.call(value) === '[object Boolean]') {
    value = value ? 'yes' : 'no'
  }

  if (AutoRotateValues.indexOf(value) === -1) {
    throw new TypeError('Value must be one of ' + ProgressiveValues)
  }

  return appendOp(url, '-/autorotate/' + value + '/')
}

function isInt (value) {
  return (Object.prototype.toString.call(value) === '[object Number]' && parseFloat(value) === parseInt(value, 10)) && !isNaN(value)
}

exports.sharp = function (url, value) {
  if (value == null) {
    value = 5
  }

  if (Object.prototype.toString.call(value) === '[object String]') {
    value = parseInt(value, 10)
  }

  if (!isInt(value) || value < 0 || value > 20) {
    throw new TypeError('Sharpness must be an integer from 0 to 20')
  }

  return appendOp(url, '-/sharp/' + value + '/')
}

exports.blur = function (url, radius) {
  if (radius == null) {
    radius = 10
  }

  if (Object.prototype.toString.call(radius) === '[object String]') {
    radius = parseInt(radius, 10)
  }

  if (!isInt(radius) || radius < 0 || radius > 5000) {
    throw new TypeError('Blur radius must be an integer from 0 to 5000')
  }

  return appendOp(url, '-/blur/' + radius + '/')
}

exports.rotate = function (url, angle) {
  if (angle == null) {
    angle = 0
  }

  if (Object.prototype.toString.call(angle) === '[object String]') {
    angle = parseInt(angle, 10)
  }

  if (!isInt(angle) || angle % 90 !== 0) {
    throw new TypeError('Angle must be an integer and multiple of 90')
  }

  return appendOp(url, '-/rotate/' + angle + '/')
}

exports.flip = function (url) {
  return appendOp(url, '-/flip/')
}

exports.mirror = function (url) {
  return appendOp(url, '-/mirror/')
}

exports.greyscale = function (url) {
  return appendOp(url, '-/greyscale/')
}

exports.invert = function (url) {
  return appendOp(url, '-/invert/')
}

exports.nthImage = function (url, index) {
  return appendOp(url, 'nth/' + (index || 0))
}
<commit_msg>nthImage method adds trailing slash to URL<commit_after>function appendOp (url, op) {
  var parts = url.split('/')

  if (url[url.length - 1] === '/') {
    parts[parts.length - 1] = op
  } else {
    parts[parts.length - 1] = op + parts[parts.length - 1]
  }

  return parts.join('/')
}

var FormatValues = ['png', 'jpeg']

exports.format = function (url, type) {
  if (FormatValues.indexOf(type) === -1) {
    throw new TypeError('Format must be one of ' + FormatValues)
  }

  return appendOp(url, '-/format/' + type + '/')
}

var QualityValues = ['normal', 'better', 'best', 'lighter', 'lightest']

exports.quality = function (url, value) {
  if (QualityValues.indexOf(value) === -1) {
    throw new TypeError('Quality must be one of ' + QualityValues)
  }

  return appendOp(url, '-/quality/' + value + '/')
}

var ProgressiveValues = ['yes', 'no']

exports.progressive = function (url, value) {
  if (Object.prototype.toString.call(value) === '[object Boolean]') {
    value = value ? 'yes' : 'no'
  }

  if (ProgressiveValues.indexOf(value) === -1) {
    throw new TypeError('Value must be one of ' + ProgressiveValues)
  }

  return appendOp(url, '-/progressive/' + value + '/')
}

var PreviewRegex = /^[0-9]+x[0-9]+$/

exports.preview = function (url, dims) {
  if (!PreviewRegex.test(dims)) {
    throw new TypeError('Invalid dimensions format, expected format example: 200x200')
  }

  return appendOp(url, '-/preview/' + dims + '/')
}

var ResizeRegex = /^([0-9]+x)|([0-9]+x[0-9]+)|(x[0-9]+)$/

exports.resize = function (url, dims) {
  if (!ResizeRegex.test(dims)) {
    throw new TypeError('Invalid dimensions format, expected format examples: 200x200, x200, 200x')
  }

  return appendOp(url, '-/resize/' + dims + '/')
}

var CropDimsRegex = /^[0-9]+x[0-9]+$/
var CropCoordsRegex = /^([0-9]+,[0-9])|center+$/

exports.crop = function (url, dims, coords) {
  if (!CropDimsRegex.test(dims)) {
    throw new TypeError('Invalid dimensions format, expected format example: 200x200')
  }

  if (coords) {
    if (!CropCoordsRegex.test(coords)) {
      throw new TypeError('Invalid coordinates format, expected format examples: 1400,1800, center')
    }

    return appendOp(url, '-/crop/' + dims + '/' + encodeURIComponent(coords) + '/')
  }

  return appendOp(url, '-/crop/' + dims + '/')
}

var ScaleCropDimsRegex = /^[0-9]+x[0-9]+$/

exports.scaleCrop = function (url, dims, center) {
  if (!ScaleCropDimsRegex.test(dims)) {
    throw new TypeError('Invalid dimensions format, expected format example: 200x200')
  }

  return appendOp(url, '-/scale_crop/' + dims + '/' + (center ? 'center/' : ''))
}

var StretchValues = ['on', 'off', 'fill']

exports.stretch = function (url, value) {
  if (StretchValues.indexOf(value) === -1) {
    throw new TypeError('Stretch must be one of ' + StretchValues)
  }

  return appendOp(url, '-/stretch/' + value + '/')
}

var SetFillRegex = /^[a-f0-9]{6}$/

exports.setFill = function (url, color) {
  if (!SetFillRegex.test(color)) {
    throw new TypeError('Color must be in hexadecimal notation')
  }

  return appendOp(url, '-/setfill/' + color + '/')
}

var AutoRotateValues = ['yes', 'no']

exports.autoRotate = function (url, value) {
  if (Object.prototype.toString.call(value) === '[object Boolean]') {
    value = value ? 'yes' : 'no'
  }

  if (AutoRotateValues.indexOf(value) === -1) {
    throw new TypeError('Value must be one of ' + ProgressiveValues)
  }

  return appendOp(url, '-/autorotate/' + value + '/')
}

function isInt (value) {
  return (Object.prototype.toString.call(value) === '[object Number]' && parseFloat(value) === parseInt(value, 10)) && !isNaN(value)
}

exports.sharp = function (url, value) {
  if (value == null) {
    value = 5
  }

  if (Object.prototype.toString.call(value) === '[object String]') {
    value = parseInt(value, 10)
  }

  if (!isInt(value) || value < 0 || value > 20) {
    throw new TypeError('Sharpness must be an integer from 0 to 20')
  }

  return appendOp(url, '-/sharp/' + value + '/')
}

exports.blur = function (url, radius) {
  if (radius == null) {
    radius = 10
  }

  if (Object.prototype.toString.call(radius) === '[object String]') {
    radius = parseInt(radius, 10)
  }

  if (!isInt(radius) || radius < 0 || radius > 5000) {
    throw new TypeError('Blur radius must be an integer from 0 to 5000')
  }

  return appendOp(url, '-/blur/' + radius + '/')
}

exports.rotate = function (url, angle) {
  if (angle == null) {
    angle = 0
  }

  if (Object.prototype.toString.call(angle) === '[object String]') {
    angle = parseInt(angle, 10)
  }

  if (!isInt(angle) || angle % 90 !== 0) {
    throw new TypeError('Angle must be an integer and multiple of 90')
  }

  return appendOp(url, '-/rotate/' + angle + '/')
}

exports.flip = function (url) {
  return appendOp(url, '-/flip/')
}

exports.mirror = function (url) {
  return appendOp(url, '-/mirror/')
}

exports.greyscale = function (url) {
  return appendOp(url, '-/greyscale/')
}

exports.invert = function (url) {
  return appendOp(url, '-/invert/')
}

exports.nthImage = function (url, index) {
  return appendOp(url, 'nth/' + (index || 0) + '/')
}
<|endoftext|>