<commit_before>'use strict';

var expect = require('chai').expect;
var _ = require('lodash');
var checkTypes = require('check-types');
var Joi = require('joi');

// setup Chai
var chai = require('chai');
chai.should(); // setup should assertions
chai.use(require('chai-things'));
chai.config.includeStack = false;
global.expect = chai.expect;

var pathMatch = {};

// performs a setup operation by checking the input data and merging the input data with a set of defaults
// returns the result of merging the default options and the input data
function setup(check) {
    if (!check) {
        throw new Error('Data to match is not defined');
    } else if (!check.jsonBody) {
        throw new Error('jsonBody is not defined');
    } else if (!check.jsonTest) {
        throw new Error('jsonTest is not defined');
    }

    // define the defaults
    var defaults = {
        isNot: false,
        path: undefined
        // jsonBody will be present
        // jsonTest will be present
    };

    // merge the passed in values with the defaults
    return _.merge(defaults, check);
}

// applies a path traversal by navigating through the jsonBody
// returns an object containing the last option specified in the path (*, ? or undefined) and
// the traversed json body
function applyPath(path, jsonBody, isNot) {
    // TODO input validation
    // * path cannot end in '.'
    // * path cannot be ''
    // * path cannot have more than one '*'/'?'
    // * path cannot start with ? or * and have more stuff after

    // states the last option in the path
    var lastOption = undefined;

    // split up the path by '.'
    var pathSegments = path.split('.');
    // temporarially store the last option
    var tmpLast = pathSegments[pathSegments.length - 1];
    // if the last option is not a '*' or '?', set it to unefined as the developer didn't specify one
    if ('*' === tmpLast || '?' === tmpLast) {
        lastOption = tmpLast;
    }

    try {
        // break apart the path and iterate through the keys to traverse through the JSON object
        _.forEach(pathSegments, function(segment) {
            // if the next 'segment' isn't actually a special character, traverse through the object
            if('*' !== segment && '?' !== segment) {
                jsonBody = jsonBody[segment];
            }
        });
    } catch(e) {
        if(!isNot) {
            throw e;
        } else {
            console.warn("[IcedFrisby] You attempted to traverse through an object with a path ('" + path + "') that did not exist in the object. \
            This issue was suppressed because you specified the isNot option. This behavior is usually considered an anti-pattern. Use a schema check instead.");
        }
    }

    return {
        lastOption: lastOption,
        jsonBody: jsonBody
    };
}

// performs a complete JSON match
pathMatch.matchJSON = function(check) {
    // setup the data (validate check object, apply defaults)
    check = setup(check);

    // states the last option specified in the path (undefined, '*', or '?')
    var lastOption = undefined;

    // traverse through a deep object if needed
    if(check.path) {
        var results = applyPath(check.path, check.jsonBody, check.isNot);
        lastOption = results.lastOption;
        check.jsonBody = results.jsonBody;
    }

    // EACH item in array should match
    if('*' === lastOption) {
        // assert that jsonBody is an array
        checkTypes.assert.array(check.jsonBody);

        _.forEach(check.jsonBody, function(json) {
            if (check.isNot) {
                expect(json).to.not.deep.equal(check.jsonTest);
            } else {
                expect(json).to.deep.equal(check.jsonTest);
            }
        });

    // ONE item in array should match
    } else if('?' === lastOption) {
        // assert that jsonBody is an array
        checkTypes.assert.array(check.jsonBody);

        var itemCount = check.jsonBody.length;

        // check if there are any objects to match against. Don't do this for the .not case - having 0 elements would be valid.
        if (0 === itemCount && !check.isNot) {
            throw new Error('There are no JSON objects to match against');
        }

        if (check.isNot) {
            check.jsonBody.should.not.include.something.that.deep.equals(check.jsonTest);
        } else {
            check.jsonBody.should.include.something.that.deep.equals(check.jsonTest);
        }

    // Normal matcher, entire object/array should match
    } else {
        if (check.isNot) {
            expect(check.jsonBody).to.not.deep.equal(check.jsonTest);
        } else {
            expect(check.jsonBody).to.deep.equal(check.jsonTest);
        }
    }
}

// performs a complete JSON type match with Joi
pathMatch.matchJSONTypes = function(check) {
    // setup the data (validate check object, apply defaults)
    check = setup(check);

    // states the last option specified in the path (undefined, '*', or '?')
    var lastOption = undefined;

    // traverse through a deep object if needed
    if(check.path) {
        var results = applyPath(check.path, check.jsonBody, check.isNot);
        lastOption = results.lastOption;
        check.jsonBody = results.jsonBody;
    }

    // EACH item in array should match
    if('*' === lastOption) {
        checkTypes.assert.array(check.jsonBody, "Expected an Array in the path '" + check.path + "' but got " + typeof(check.jsonBody));

        var errorCount = 0;
        _.forEach(check.jsonBody, function(json) {
            // expect(json).toContainJsonTypes(jsonTest, self.current.isNot);
            Joi.validate(json, check.jsonTest, function(err, value) {
                if (err) {
                    if (check.isNot) {
                        // there is an error but isNot case is true. Increment counter.
                        errorCount++;
                    } else {
                        throw err;
                    }
                }
            });
        });

        // if this is the isNot case, ALL the validations should have failed for the '*' case
        if (check.isNot) {
            var delta = check.jsonBody.length - errorCount;
            // if the error count is not the same as the number of elements, something validated successfully - which is a problem
            if (0 !== delta) {
                throw new Error('Expected all objects to be invalid but ' + delta + '/' + check.jsonBody.length + ' objects validated successfully');
            }
        }

    // ONE item in array should match
    } else if('?' === lastOption) {
        checkTypes.assert.array(check.jsonBody, "Expected an Array in the path '" + check.path + "' but got " + typeof(check.jsonBody));

        var itemCount = check.jsonBody.length;
        var errorCount = 0;

        // check if there are any objects to match against. Don't do this for the .not case - having 0 elements would be valid.
        if (0 === itemCount && !check.isNot) {
            throw new Error("There are no JSON objects to match against");
        }

        for(var i = 0; i < itemCount; i++) {
            Joi.validate(check.jsonBody[i], check.jsonTest, function(err, value) {
                if (err) {
                    // didn't match this object, increment number of errors
                    errorCount++;
                }
            });
        }

        // If all errors, test fails
        if(itemCount === errorCount && !check.isNot) {
            var objPlural = itemCount > 1 ? "objects" : "object";
            throw new Error("Expected one out of " + itemCount + " " + objPlural + " to match provided JSON types");
        }
    // Normal matcher, entire object/array should match
    } else {
        Joi.validate(check.jsonBody, check.jsonTest, function(err, value) {
            if (err && !check.isNot) {
                throw err;
            }
        });
    }
}

module.exports = pathMatch;
<commit_msg>Fix most JSHint issues.<commit_after>/*jshint node: true */
/*jshint multistr: true */
'use strict';

var expect = require('chai').expect;
var _ = require('lodash');
var checkTypes = require('check-types');
var Joi = require('joi');

// setup Chai
var chai = require('chai');
chai.should(); // setup should assertions
chai.use(require('chai-things'));
chai.config.includeStack = false;
global.expect = chai.expect;

var pathMatch = {};

// performs a setup operation by checking the input data and merging the input data with a set of defaults
// returns the result of merging the default options and the input data
function setup(check) {
    if (!check) {
        throw new Error('Data to match is not defined');
    } else if (!check.jsonBody) {
        throw new Error('jsonBody is not defined');
    } else if (!check.jsonTest) {
        throw new Error('jsonTest is not defined');
    }

    // define the defaults
    var defaults = {
        isNot: false,
        path: undefined
        // jsonBody will be present
        // jsonTest will be present
    };

    // merge the passed in values with the defaults
    return _.merge(defaults, check);
}

// applies a path traversal by navigating through the jsonBody
// returns an object containing the last option specified in the path (*, ? or undefined) and
// the traversed json body
function applyPath(path, jsonBody, isNot) {
    // TODO input validation
    // * path cannot end in '.'
    // * path cannot be ''
    // * path cannot have more than one '*'/'?'
    // * path cannot start with ? or * and have more stuff after

    // states the last option in the path
    var lastOption;

    // split up the path by '.'
    var pathSegments = path.split('.');
    // temporarially store the last option
    var tmpLast = pathSegments[pathSegments.length - 1];
    // if the last option is not a '*' or '?', set it to unefined as the developer didn't specify one
    if ('*' === tmpLast || '?' === tmpLast) {
        lastOption = tmpLast;
    }

    try {
        // break apart the path and iterate through the keys to traverse through the JSON object
        _.forEach(pathSegments, function(segment) {
            // if the next 'segment' isn't actually a special character, traverse through the object
            if('*' !== segment && '?' !== segment) {
                jsonBody = jsonBody[segment];
            }
        });
    } catch(e) {
        if(!isNot) {
            throw e;
        } else {
            console.warn("[IcedFrisby] You attempted to traverse through an object with a path ('" + path + "') that did not exist in the object. \
            This issue was suppressed because you specified the isNot option. This behavior is usually considered an anti-pattern. Use a schema check instead.");
        }
    }

    return {
        lastOption: lastOption,
        jsonBody: jsonBody
    };
}

// performs a complete JSON match
pathMatch.matchJSON = function(check) {
    // setup the data (validate check object, apply defaults)
    check = setup(check);

    // states the last option specified in the path (undefined, '*', or '?')
    var lastOption;

    // traverse through a deep object if needed
    if(check.path) {
        var results = applyPath(check.path, check.jsonBody, check.isNot);
        lastOption = results.lastOption;
        check.jsonBody = results.jsonBody;
    }

    // EACH item in array should match
    if('*' === lastOption) {
        // assert that jsonBody is an array
        checkTypes.assert.array(check.jsonBody);

        _.forEach(check.jsonBody, function(json) {
            if (check.isNot) {
                expect(json).to.not.deep.equal(check.jsonTest);
            } else {
                expect(json).to.deep.equal(check.jsonTest);
            }
        });

    // ONE item in array should match
    } else if('?' === lastOption) {
        // assert that jsonBody is an array
        checkTypes.assert.array(check.jsonBody);

        var itemCount = check.jsonBody.length;

        // check if there are any objects to match against. Don't do this for the .not case - having 0 elements would be valid.
        if (0 === itemCount && !check.isNot) {
            throw new Error('There are no JSON objects to match against');
        }

        if (check.isNot) {
            check.jsonBody.should.not.include.something.that.deep.equals(check.jsonTest);
        } else {
            check.jsonBody.should.include.something.that.deep.equals(check.jsonTest);
        }

    // Normal matcher, entire object/array should match
    } else {
        if (check.isNot) {
            expect(check.jsonBody).to.not.deep.equal(check.jsonTest);
        } else {
            expect(check.jsonBody).to.deep.equal(check.jsonTest);
        }
    }
};

// performs a complete JSON type match with Joi
pathMatch.matchJSONTypes = function(check) {
    // setup the data (validate check object, apply defaults)
    check = setup(check);

    // states the last option specified in the path (undefined, '*', or '?')
    var lastOption;

    // traverse through a deep object if needed
    if(check.path) {
        var results = applyPath(check.path, check.jsonBody, check.isNot);
        lastOption = results.lastOption;
        check.jsonBody = results.jsonBody;
    }

    // EACH item in array should match
    if('*' === lastOption) {
        checkTypes.assert.array(check.jsonBody, "Expected an Array in the path '" + check.path + "' but got " + typeof(check.jsonBody));

        var errorCount = 0;
        _.forEach(check.jsonBody, function(json) {
            // expect(json).toContainJsonTypes(jsonTest, self.current.isNot);
            Joi.validate(json, check.jsonTest, function(err, value) {
                if (err) {
                    if (check.isNot) {
                        // there is an error but isNot case is true. Increment counter.
                        errorCount++;
                    } else {
                        throw err;
                    }
                }
            });
        });

        // if this is the isNot case, ALL the validations should have failed for the '*' case
        if (check.isNot) {
            var delta = check.jsonBody.length - errorCount;
            // if the error count is not the same as the number of elements, something validated successfully - which is a problem
            if (0 !== delta) {
                throw new Error('Expected all objects to be invalid but ' + delta + '/' + check.jsonBody.length + ' objects validated successfully');
            }
        }

    // ONE item in array should match
    } else if('?' === lastOption) {
        checkTypes.assert.array(check.jsonBody, "Expected an Array in the path '" + check.path + "' but got " + typeof(check.jsonBody));

        var itemCount = check.jsonBody.length;
        var errorCount = 0;

        // check if there are any objects to match against. Don't do this for the .not case - having 0 elements would be valid.
        if (0 === itemCount && !check.isNot) {
            throw new Error("There are no JSON objects to match against");
        }

        for(var i = 0; i < itemCount; i++) {
            Joi.validate(check.jsonBody[i], check.jsonTest, function(err, value) {
                if (err) {
                    // didn't match this object, increment number of errors
                    errorCount++;
                }
            });
        }

        // If all errors, test fails
        if(itemCount === errorCount && !check.isNot) {
            var objPlural = itemCount > 1 ? "objects" : "object";
            throw new Error("Expected one out of " + itemCount + " " + objPlural + " to match provided JSON types");
        }
    // Normal matcher, entire object/array should match
    } else {
        Joi.validate(check.jsonBody, check.jsonTest, function(err, value) {
            if (err && !check.isNot) {
                throw err;
            }
        });
    }
};

module.exports = pathMatch;
<|endoftext|>


<commit_before>var fileSystem = require('fs');
var path = require('path');
var express = require('express');
var request = require('request');

var app = express();

app.get('/', function(request, response){
  response.sendFile(__dirname + "/Pages/Home/home.html");
});
app.get('/home.js', function(request, response){
  response.sendFile(__dirname + "/Pages/Home/home.js");
});

// Weather Forecast via Forecast.io
var apiKeyDirectory = path.resolve(__dirname, '..', 'apikeys');
var forecastApiKeyFullPath = path.join(apiKeyDirectory, 'forecast');
var cities = [
  { name: 'Blue Bell, PA', coordinates: [40.144722, -75.268889] }
];
var forecastApiKey = fileSystem.readFile(forecastApiKeyFullPath, {encoding: 'utf-8'}, function(err, data){
  var path = 'https://api.forecast.io/forecast/' + data.slice(0, data.length-1) + '/' + cities[0].coordinates[0] + ',' + cities[0].coordinates[1];
  request(path, function(err, response, body){
    if (err) console.log(err);
    else {
      var currentWeather = JSON.parse(body);
      console.log('Currently: ' + currentWeather.currently.summary);
      console.log('Temperature: ' + currentWeather.currently.temperature);
      console.log('Wind Speed: ' + currentWeather.currently.windSpeed + 'mph');
      console.log('Hourly Forecast: ' + currentWeather.hourly.summary);
      console.log('Daily Forecast: ' + currentWeather.daily.summary);
    }
  });
});

var server = app.listen(80, function() {
  var host = server.address().address
  var port = server.address().port

  console.log('Listening at http://%s:%s', host, port);
});
<commit_msg>Added minimal error handling/logging around forecast API key load.<commit_after>var fileSystem = require('fs');
var path = require('path');
var express = require('express');
var request = require('request');

var app = express();

app.get('/', function(request, response){
  response.sendFile(__dirname + "/Pages/Home/home.html");
});
app.get('/home.js', function(request, response){
  response.sendFile(__dirname + "/Pages/Home/home.js");
});

// Weather Forecast via Forecast.io
var apiKeyDirectory = path.resolve(__dirname, '..', 'apikeys');
var forecastApiKeyFullPath = path.join(apiKeyDirectory, 'forecast');
var cities = [
  { name: 'Blue Bell, PA', coordinates: [40.144722, -75.268889] }
];
var forecastApiKey = fileSystem.readFile(forecastApiKeyFullPath, {encoding: 'utf-8'}, function(err, data){
  if (err) {
    console.log('Error loading forecast API key: ' + err);
    process.exit(1);
    return;
  }

  var path = 'https://api.forecast.io/forecast/' + data.slice(0, data.length-1) + '/' + cities[0].coordinates[0] + ',' + cities[0].coordinates[1];
  request(path, function(err, response, body){
    if (err) console.log(err);
    else {
      var currentWeather = JSON.parse(body);
      console.log('Currently: ' + currentWeather.currently.summary);
      console.log('Temperature: ' + currentWeather.currently.temperature);
      console.log('Wind Speed: ' + currentWeather.currently.windSpeed + 'mph');
      console.log('Hourly Forecast: ' + currentWeather.hourly.summary);
      console.log('Daily Forecast: ' + currentWeather.daily.summary);
    }
  });
});

var server = app.listen(80, function() {
  var host = server.address().address
  var port = server.address().port

  console.log('Listening at http://%s:%s', host, port);
});
<|endoftext|>


<commit_before>import React from 'react'
import ReactDOMServer from 'react-dom/server'
import Home from './home'
import MaxForLiveDevices from './max-for-live'
import MiniakPatchEditor from './miniak-patch-editor'
import WacNetworkMidi from './wac-network-midi'
import Error from './error'
import { readFile, writeFile } from './files/'

const html = css => component => `<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>chippanfire.com</title>
    <link rel="icon" href="favicon.ico" type="image/x-icon" />
    <style>
${css}
    </style>
  </head>
  <body>
    ${ReactDOMServer.renderToStaticMarkup(component)}
  </body>
</html>
`

readFile('./app.css')
  .then(html)
  .then(render => Promise.all([
    Promise.resolve(<Home />).then(render).then(writeFile('../dist/index.html')),
    Promise.resolve(<Error />).then(render).then(writeFile('../dist/error.html')),
    Promise.resolve(<MaxForLiveDevices />).then(render).then(writeFile('../dist/max-for-live-devices.html')),
    Promise.resolve(<MiniakPatchEditor />).then(render).then(writeFile('../dist/miniak-patch-editor.html')),
    Promise.resolve(<WacNetworkMidi />).then(render).then(writeFile('../dist/wac-network-midi.html')),
    Promise.resolve('User-agent: *\nDisallow:').then(writeFile('../dist/robots.txt'))
  ]))
<commit_msg>Move favicon <link> above <title>. Also make it not self-closing<commit_after>import React from 'react'
import ReactDOMServer from 'react-dom/server'
import Home from './home'
import MaxForLiveDevices from './max-for-live'
import MiniakPatchEditor from './miniak-patch-editor'
import WacNetworkMidi from './wac-network-midi'
import Error from './error'
import { readFile, writeFile } from './files/'

const html = css => component => `<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="icon" href="favicon.ico" type="image/x-icon">
    <title>chippanfire.com</title>
    <style>
${css}
    </style>
  </head>
  <body>
    ${ReactDOMServer.renderToStaticMarkup(component)}
  </body>
</html>
`

readFile('./app.css')
  .then(html)
  .then(render => Promise.all([
    Promise.resolve(<Home />).then(render).then(writeFile('../dist/index.html')),
    Promise.resolve(<Error />).then(render).then(writeFile('../dist/error.html')),
    Promise.resolve(<MaxForLiveDevices />).then(render).then(writeFile('../dist/max-for-live-devices.html')),
    Promise.resolve(<MiniakPatchEditor />).then(render).then(writeFile('../dist/miniak-patch-editor.html')),
    Promise.resolve(<WacNetworkMidi />).then(render).then(writeFile('../dist/wac-network-midi.html')),
    Promise.resolve('User-agent: *\nDisallow:').then(writeFile('../dist/robots.txt'))
  ]))
<|endoftext|>


<commit_before>angular.module('processMonitor.controllers', ['processMonitor.services', 'processMonitor.directives', 'angularTree'])
    .controller('MainController', ['$scope', 'statusService',
        function($scope, statusService) {
            $scope.status_processes = statusService.status_processes;
        }])
    .controller('ProcessTree', ['$scope', 'statusService',
        function($scope, statusService) {
            $scope.processes = statusService.status_processes;
            $scope.colors = {
                true:'#99CCFF',
                false:'white'
            };

            $scope.selection_class = {

            };

            $scope.selected = function () {
                console.log(this.item.pid + ' is selected: ' + this.$selected);
                if (this.$selected) {
                    $scope.selected_pid = this.item.pid;
                }
            };
        }])
    .controller('Tree', ['$scope', 'statusService',
        function($scope, statusService) {
            console.log("Tree controller instantiated.");
            $scope.processes = statusService.status_processes;
        }])
    .controller('BasicData', ['$scope', 'statusService',
        function($scope, statusService) {
            $scope.status_all = statusService.status_all;
        }]);<commit_msg>got ng-click working on individual process boxes<commit_after>angular.module('processMonitor.controllers', ['processMonitor.services', 'processMonitor.directives', 'angularTree'])
    .controller('MainController', ['$scope', 'statusService',
        function($scope, statusService) {
            $scope.status_processes = statusService.status_processes;
        }])
    .controller('ProcessTree', ['$scope', 'statusService',
        function($scope, statusService) {
            $scope.processes = statusService.status_processes;
            $scope.colors = {
                true:'#99CCFF',
                false:'white'
            };

            $scope.selection_class = {

            };

            $scope.getData = function (pid) {
                console.log(["Selected", pid].join(" "));
//                if (this.$selected) {
//                    $scope.selected_pid = this.item.pid;
//                }
            };
        }])
    .controller('Tree', ['$scope', 'statusService',
        function($scope, statusService) {
            console.log("Tree controller instantiated.");
            $scope.processes = statusService.status_processes;

            $scope.getData = function (pid) {
                console.log(["Selected", pid].join(" "));
            };
        }])
    .controller('BasicData', ['$scope', 'statusService',
        function($scope, statusService) {
            $scope.status_all = statusService.status_all;
        }]);<|endoftext|>


<commit_before>'use strict';

import arangojs, {Database, aqlQuery} from 'arangojs';

let db = arangojs({databaseName: "test", url: "http://localhost:8529"})

let createVertex = async (attrs, collection) => {
  //FIXME: use the collection variable
  //insert a new vertex for the attribute
  let insertionQuery = aqlQuery`
    UPSERT ${attrs}
      INSERT ${attrs}
      UPDATE {}
      IN vertices
        RETURN NEW
  `
  let insertionCursor = await db.query(insertionQuery)
  return insertionCursor.all()
}

module.exports.createVertex = createVertex;

let removeAttribute = async (example, collection) => {
  //Then remove the attribute from existing vertices
  //FIXME: use the collection variable
  let aql = aqlQuery`
    FOR vertex IN vertices
      FILTER MATCHES(vertex, ${example})
        REPLACE vertex WITH UNSET(vertex, ATTRIBUTES(${example})) IN vertices
          RETURN NEW
  `
  let cursor = await db.query(aql)
  return cursor.all()
}

module.exports.removeAttribute = removeAttribute;

let attributeToVertex = async (example, options) => {

  var action = String((args) => {

    var db = require("internal").db;

    var example = args[0]
    var options = args[1]

    if(options.additional_attrs){
      var additional_vertex_attributes = options.additional_attrs.vertex
      var additional_edge_attributes = options.additional_attrs.edge
    } else {
      var additional_vertex_attributes = {}
      var additional_edge_attributes = {}
    }

    var vertexCollection = db._collection('vertices')
    var edgesCollection = db._collection('edges')

    var removeAttributesAQL = `
      FOR vertex IN vertices
      FILTER MATCHES(vertex, @example)
      REPLACE vertex WITH UNSET(vertex, ATTRIBUTES(@example)) IN @@collection
      RETURN NEW
    `
    //All the vertices that have had an attribute removed
    var verticesWithAttrsRemoved = db._query(removeAttributesAQL, {example: example, "@collection": "vertices"}).toArray()

    var createVertexAQL = `
    INSERT MERGE(@attrs, @additional_attrs)
    IN @@collection
      RETURN NEW
    `
    var newVertex = db._query(createVertexAQL, {attrs: example, additional_attrs: additional_vertex_attributes, "@collection": "vertices"}).toArray()[0]

    //verticesWithAttrsRemoved is an array of all the documents we removed the
    //attribute from.
    //Now we create edges either to or from all the vertices we removed
    //the attribute from to the newly created vertex
    if(options.direction == "inbound") {
      var createEdgesAQL = `
      FOR vertex IN @verticesWithAttrsRemoved
        LET merged = (MERGE({ _to: @newVertexID, _from: vertex._id }, @additional_attrs))
        INSERT merged
        IN @@collection
          RETURN NEW
      `
    } else {
      var createEdgesAQL = `
      FOR vertex IN @verticesWithAttrsRemoved
        LET merged = (MERGE({ _from: @newVertexID, _to: vertex._id }, @additional_attrs))
        INSERT merged
        IN @@collection
          RETURN NEW
      `
    }
    var edges = db._query(createEdgesAQL, {verticesWithAttrsRemoved: verticesWithAttrsRemoved, additional_attrs: additional_edge_attributes,  newVertexID: newVertex._id, "@collection": 'edges'}).toArray()

    //In theory all went well.
    return newVertex
  })
  await db.transaction({write: ['vertices', 'edges']}, action, [example, options])
};

module.exports.attributeToVertex = attributeToVertex;
<commit_msg>Remove unused variables<commit_after>'use strict';

import arangojs, {Database, aqlQuery} from 'arangojs';

let db = arangojs({databaseName: "test", url: "http://localhost:8529"})

let createVertex = async (attrs, collection) => {
  //FIXME: use the collection variable
  //insert a new vertex for the attribute
  let insertionQuery = aqlQuery`
    UPSERT ${attrs}
      INSERT ${attrs}
      UPDATE {}
      IN vertices
        RETURN NEW
  `
  let insertionCursor = await db.query(insertionQuery)
  return insertionCursor.all()
}

module.exports.createVertex = createVertex;

let removeAttribute = async (example, collection) => {
  //Then remove the attribute from existing vertices
  //FIXME: use the collection variable
  let aql = aqlQuery`
    FOR vertex IN vertices
      FILTER MATCHES(vertex, ${example})
        REPLACE vertex WITH UNSET(vertex, ATTRIBUTES(${example})) IN vertices
          RETURN NEW
  `
  let cursor = await db.query(aql)
  return cursor.all()
}

module.exports.removeAttribute = removeAttribute;

let attributeToVertex = async (example, options) => {

  var action = String((args) => {

    var db = require("internal").db;

    var example = args[0]
    var options = args[1]

    if(options.additional_attrs){
      var additional_vertex_attributes = options.additional_attrs.vertex
      var additional_edge_attributes = options.additional_attrs.edge
    } else {
      var additional_vertex_attributes = {}
      var additional_edge_attributes = {}
    }

    var removeAttributesAQL = `
      FOR vertex IN vertices
      FILTER MATCHES(vertex, @example)
      REPLACE vertex WITH UNSET(vertex, ATTRIBUTES(@example)) IN @@collection
      RETURN NEW
    `
    //All the vertices that have had an attribute removed
    var verticesWithAttrsRemoved = db._query(removeAttributesAQL, {example: example, "@collection": "vertices"}).toArray()

    var createVertexAQL = `
    INSERT MERGE(@attrs, @additional_attrs)
    IN @@collection
      RETURN NEW
    `
    var newVertex = db._query(createVertexAQL, {attrs: example, additional_attrs: additional_vertex_attributes, "@collection": "vertices"}).toArray()[0]

    //verticesWithAttrsRemoved is an array of all the documents we removed the
    //attribute from.
    //Now we create edges either to or from all the vertices we removed
    //the attribute from to the newly created vertex
    if(options.direction == "inbound") {
      var createEdgesAQL = `
      FOR vertex IN @verticesWithAttrsRemoved
        LET merged = (MERGE({ _to: @newVertexID, _from: vertex._id }, @additional_attrs))
        INSERT merged
        IN @@collection
          RETURN NEW
      `
    } else {
      var createEdgesAQL = `
      FOR vertex IN @verticesWithAttrsRemoved
        LET merged = (MERGE({ _from: @newVertexID, _to: vertex._id }, @additional_attrs))
        INSERT merged
        IN @@collection
          RETURN NEW
      `
    }
    var edges = db._query(createEdgesAQL, {verticesWithAttrsRemoved: verticesWithAttrsRemoved, additional_attrs: additional_edge_attributes,  newVertexID: newVertex._id, "@collection": 'edges'}).toArray()

    //In theory all went well.
    return newVertex
  })
  await db.transaction({write: ['vertices', 'edges']}, action, [example, options])
};

module.exports.attributeToVertex = attributeToVertex;
<|endoftext|>


<commit_before>/**
 * Copyright (C) 2014, Oliver Salzburg
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 * Created: 2014-01-20 21:05
 *
 * @author Oliver Salzburg
 * @copyright Copyright (C) 2014, Oliver Salzburg, HARTWIG Communication & Events
 * @license http://opensource.org/licenses/mit-license.php MIT License
 */

(function() {
	"use strict";

	var i18nModule = angular.module( "i18n", [] );

	i18nModule.provider( "i18n", function() {
		var i18nProvider = this;

		i18nProvider.objectNotation = ".";
		i18nProvider.setObjectNotation = function( delimiter ) {
			i18nProvider.objectNotation = delimiter;
		};

		/**
		 * The main i18n service which handles retrieval of the translation map sends single translation terms to the backend.
		 */
		i18nProvider.$get = [ "$rootScope", "$http", "$q", function( $rootScope, $http, $q ) {
			var i18nService = function() {

				// We use this deferred to keep track of if the last locale loading request has completed.
				this._localeLoadedDeferred = $q.defer();
				// If a lot of locale loading is requested, we collect all the promises on this stack so we can later resolve them.
				this._deferredStack = [];

				// A handy boolean that indicates if the currently requested locale was loaded.
				this.loaded = false;

				// Initialize the service with a given locale.
				this.init = function( locale ) {
					if( locale != this.userLanguage ) {
						if( this._localeLoadedDeferred ) {
							this._deferredStack.push( this._localeLoadedDeferred );
						}
						this._localeLoadedDeferred = $q.defer();
						this.loaded = false;
						this.userLanguage = locale;

						var service = this;

						$http( {
							method : "get",
							url    : "/i18n/" + locale,
							cache  : true
						} ).success( function( translations ) {
							$rootScope.i18n = translations;
							service.loaded = true;
							service._localeLoadedDeferred.resolve( $rootScope.i18n );

							while( service._deferredStack.length ) {
								service._deferredStack.pop().resolve( $rootScope.i18n );
							}
						} );
					}

					return this._localeLoadedDeferred.promise;
				};

				/**
				 * Syntactic sugar. Returns a promise to return the i18n service, once the translation map is loaded.
				 * @returns {defer.promise|*|promise}
				 */
				this.i18n = function() {
					var serviceDeferred = $q.defer();

					var service = this;
					this.ensureLocaleIsLoaded().then( function() {
						serviceDeferred.resolve( service );
					} );

					return serviceDeferred.promise;
				};

				/**
				 * Returns a promise to return the translation map, once it is loaded.
				 * @returns {defer.promise|*|promise}
				 */
				this.ensureLocaleIsLoaded = function() {
					return this._localeLoadedDeferred.promise;
				};

				/**
				 * Retrieve a translation object from the translation catalog, using object notation.
				 * @param {String} literal The path of the object to look up.
				 * @returns {*}
				 */
				this.getTranslationObject = function( literal ) {
					var result = literal.split( i18nProvider.objectNotation ).reduce( function( object, index ) {
						if( !object || !object.hasOwnProperty( index ) ) return null;
						return object[ index ];
					}, $rootScope.i18n );
					return result;
				};

				/**
				 * Translate a given term, using the currently loaded translation map.
				 * @param {String} name The string to translate.
				 * @returns {String} The translated string or the input, if no translation was available.
				 */
				this.__ = function( name ) {
					if( !$rootScope.i18n ) {
						return name;
					}

					var translation = $rootScope.i18n[ name ] || this.getTranslationObject( name );
					if( !translation ) {
						translation = name;

						// Temporarily store the original string in the translation table
						// to avoid future lookups causing additional GET requests to the backend.
						$rootScope.i18n[ name ] = translation;

						// Invoke the translation endpoint on the backend to cause the term to be added
						// to the translation table on the backend.
						// Additionally, store the returned, translated term in the translation table.
						// The term is very unlikely to be actually translated now, as it was most
						// likely previously unknown in the users locale, but, hey.
						$http.get( "/i18n/" + this.userLanguage + "/" + encodeURIComponent( name ) ).success( function( translated ) {
							$rootScope.i18n[ name ] = translated;
						} );
					}

					// If an implementation of vsprintf is loaded and we have additional parameters,
					// try to perform the substitution and return the result.
					if( arguments.length > 1 && typeof( vsprintf ) == "function" ) {
						translation = vsprintf( translation, Array.prototype.slice.call( arguments, 1 ) );
					}

					return translation;
				};

				/**
				 * Translate a given term and pick the singular or plural version depending on the given count.
				 * @param {Number} count The number of items, depending on which the correct translation term will be chosen.
				 * @param {String} singular The term that should be used if the count equals 1.
				 * @param {String} plural The term that should be used if the count doesn't equal 1.
				 * @returns {String} The translated phrase depending on the count.
				 */
				this.__n = function( count, singular, plural ) {
					if( !$rootScope.i18n ) {
						return singular;
					}

					var translation = $rootScope.i18n[ singular ] || this.getTranslationObject( singular );
					if( !translation ) {
						if( !plural ) {
							plural = singular;
						}

						translation = { one : singular, other : plural };

						// Temporarily store the original string in the translation table
						// to avoid future lookups causing additional GET requests to the backend.
						$rootScope.i18n[ singular ] = translation;

						// Invoke the translation endpoint on the backend to cause the term to be added
						// to the translation table on the backend.
						// Additionally, store the returned, translated term in the translation table.
						// The term is very unlikely to be actually translated now, as it was most
						// likely previously unknown in the users locale, but, hey.
						var requestUri =
							"/i18n/" +
							this.userLanguage +
							"/" +
							encodeURIComponent( singular ) +
							"?plural=" +
							encodeURIComponent( plural ) +
							"&count=" +
							encodeURIComponent( count );

						$http.get( requestUri ).success( function( translated ) {
							$rootScope.i18n[ singular ] = translated;
						} );
					}

					translation = (count == 1) ? translation.one : translation.other;

					// If an implementation of vsprintf is loaded, try to perform the substitution and return the result.
					if( typeof( vsprintf ) == "function" ) {
						translation = vsprintf( translation, [ count ] );
					}

					return translation;
				};
			};

			return new i18nService();
		} ];
	} );

	/**
	 * The i18nLocale directive can (and should) be used to tell the i18n service which locale to use.
	 * You may just want to combine it with the ngApp directive in your DOM. For example:
	 *
	 * <html ng-app="yourApp" i18n-locale="de">
	 *
	 * The "de" part should in practice be filled by the result of the i18n.getLocale() call in your express app.
	 */
	i18nModule.directive( "i18nLocale", [ "i18n", "$rootScope", function( i18n, $rootScope ) {
		return {
			restrict : "A",
			link     : function postLink( scope, element, attributes ) {
				// Observe the value provided to us and re-initialize if it changes.
				attributes.$observe( "i18nLocale", function( value ) {
					i18n.init( value );
				} );
				// Also check if a "i18nLocale" model in the scope changes its value to indicate a desired locale change.
				$rootScope.$watch( "i18nLocale", function localeChanged( newLocale, oldLocale ) {
					if( !newLocale || newLocale == oldLocale ) return;
					i18n.init( newLocale );
				} );
			}
		};
	} ] );

	/**
	 * i18n filter to be used conveniently in templates.
	 * When looking to translate just a single phrase, pass the phrase into the filter like so:
	 *
	 *   {{"My phrase"|i18n}}
	 *
	 * When you need pluralization support, pass the count into the filter, and provide the two terms as additional arguments:
	 *
	 *   {{2|i18n:"singular":"plural"}}
	 *   {{4|i18n:"%s item":"%s items"}}
	 */
	i18nModule.filter( "i18n", [
		"i18n", function( i18n ) {
			/**
			 * Check if the given input is a number.
			 * @see http://stackoverflow.com/a/1830844/259953
			 * @param n The input to check.
			 * @returns {boolean} true if the input is a number; false otherwise.
			 */
			function isNumber( n ) {
				return !isNaN( parseFloat( n ) ) && isFinite( n );
			}

			return function( input ) {
				// If the input is a number, assume pluralization is requested.
				if( isNumber( input ) ) {
					return i18n.__n.apply( i18n, arguments );
				}
				return i18n.__.apply( i18n, arguments );
			};
		}
	] );
}());
<commit_msg>[FIX] Mark filter stateful to work with Angular 1.3<commit_after>/**
 * Copyright (C) 2014, Oliver Salzburg
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 * Created: 2014-01-20 21:05
 *
 * @author Oliver Salzburg
 * @copyright Copyright (C) 2014, Oliver Salzburg, HARTWIG Communication & Events
 * @license http://opensource.org/licenses/mit-license.php MIT License
 */

(function() {
	"use strict";

	var i18nModule = angular.module( "i18n", [] );

	i18nModule.provider( "i18n", function() {
		var i18nProvider = this;

		i18nProvider.objectNotation = ".";
		i18nProvider.setObjectNotation = function( delimiter ) {
			i18nProvider.objectNotation = delimiter;
		};

		/**
		 * The main i18n service which handles retrieval of the translation map sends single translation terms to the backend.
		 */
		i18nProvider.$get = [ "$rootScope", "$http", "$q", function( $rootScope, $http, $q ) {
			var i18nService = function() {

				// We use this deferred to keep track of if the last locale loading request has completed.
				this._localeLoadedDeferred = $q.defer();
				// If a lot of locale loading is requested, we collect all the promises on this stack so we can later resolve them.
				this._deferredStack = [];

				// A handy boolean that indicates if the currently requested locale was loaded.
				this.loaded = false;

				// Initialize the service with a given locale.
				this.init = function( locale ) {
					if( locale != this.userLanguage ) {
						if( this._localeLoadedDeferred ) {
							this._deferredStack.push( this._localeLoadedDeferred );
						}
						this._localeLoadedDeferred = $q.defer();
						this.loaded = false;
						this.userLanguage = locale;

						var service = this;

						$http( {
							method : "get",
							url    : "/i18n/" + locale,
							cache  : true
						} ).success( function( translations ) {
							$rootScope.i18n = translations;
							service.loaded = true;
							service._localeLoadedDeferred.resolve( $rootScope.i18n );

							while( service._deferredStack.length ) {
								service._deferredStack.pop().resolve( $rootScope.i18n );
							}
						} );
					}

					return this._localeLoadedDeferred.promise;
				};

				/**
				 * Syntactic sugar. Returns a promise to return the i18n service, once the translation map is loaded.
				 * @returns {defer.promise|*|promise}
				 */
				this.i18n = function() {
					var serviceDeferred = $q.defer();

					var service = this;
					this.ensureLocaleIsLoaded().then( function() {
						serviceDeferred.resolve( service );
					} );

					return serviceDeferred.promise;
				};

				/**
				 * Returns a promise to return the translation map, once it is loaded.
				 * @returns {defer.promise|*|promise}
				 */
				this.ensureLocaleIsLoaded = function() {
					return this._localeLoadedDeferred.promise;
				};

				/**
				 * Retrieve a translation object from the translation catalog, using object notation.
				 * @param {String} literal The path of the object to look up.
				 * @returns {*}
				 */
				this.getTranslationObject = function( literal ) {
					var result = literal.split( i18nProvider.objectNotation ).reduce( function( object, index ) {
						if( !object || !object.hasOwnProperty( index ) ) return null;
						return object[ index ];
					}, $rootScope.i18n );
					return result;
				};

				/**
				 * Translate a given term, using the currently loaded translation map.
				 * @param {String} name The string to translate.
				 * @returns {String} The translated string or the input, if no translation was available.
				 */
				this.__ = function( name ) {
					if( !$rootScope.i18n ) {
						return name;
					}

					var translation = $rootScope.i18n[ name ] || this.getTranslationObject( name );
					if( !translation ) {
						translation = name;

						// Temporarily store the original string in the translation table
						// to avoid future lookups causing additional GET requests to the backend.
						$rootScope.i18n[ name ] = translation;

						// Invoke the translation endpoint on the backend to cause the term to be added
						// to the translation table on the backend.
						// Additionally, store the returned, translated term in the translation table.
						// The term is very unlikely to be actually translated now, as it was most
						// likely previously unknown in the users locale, but, hey.
						$http.get( "/i18n/" + this.userLanguage + "/" + encodeURIComponent( name ) ).success( function( translated ) {
							$rootScope.i18n[ name ] = translated;
						} );
					}

					// If an implementation of vsprintf is loaded and we have additional parameters,
					// try to perform the substitution and return the result.
					if( arguments.length > 1 && typeof( vsprintf ) == "function" ) {
						translation = vsprintf( translation, Array.prototype.slice.call( arguments, 1 ) );
					}

					return translation;
				};

				/**
				 * Translate a given term and pick the singular or plural version depending on the given count.
				 * @param {Number} count The number of items, depending on which the correct translation term will be chosen.
				 * @param {String} singular The term that should be used if the count equals 1.
				 * @param {String} plural The term that should be used if the count doesn't equal 1.
				 * @returns {String} The translated phrase depending on the count.
				 */
				this.__n = function( count, singular, plural ) {
					if( !$rootScope.i18n ) {
						return singular;
					}

					var translation = $rootScope.i18n[ singular ] || this.getTranslationObject( singular );
					if( !translation ) {
						if( !plural ) {
							plural = singular;
						}

						translation = { one : singular, other : plural };

						// Temporarily store the original string in the translation table
						// to avoid future lookups causing additional GET requests to the backend.
						$rootScope.i18n[ singular ] = translation;

						// Invoke the translation endpoint on the backend to cause the term to be added
						// to the translation table on the backend.
						// Additionally, store the returned, translated term in the translation table.
						// The term is very unlikely to be actually translated now, as it was most
						// likely previously unknown in the users locale, but, hey.
						var requestUri =
							"/i18n/" +
							this.userLanguage +
							"/" +
							encodeURIComponent( singular ) +
							"?plural=" +
							encodeURIComponent( plural ) +
							"&count=" +
							encodeURIComponent( count );

						$http.get( requestUri ).success( function( translated ) {
							$rootScope.i18n[ singular ] = translated;
						} );
					}

					translation = (count == 1) ? translation.one : translation.other;

					// If an implementation of vsprintf is loaded, try to perform the substitution and return the result.
					if( typeof( vsprintf ) == "function" ) {
						translation = vsprintf( translation, [ count ] );
					}

					return translation;
				};
			};

			return new i18nService();
		} ];
	} );

	/**
	 * The i18nLocale directive can (and should) be used to tell the i18n service which locale to use.
	 * You may just want to combine it with the ngApp directive in your DOM. For example:
	 *
	 * <html ng-app="yourApp" i18n-locale="de">
	 *
	 * The "de" part should in practice be filled by the result of the i18n.getLocale() call in your express app.
	 */
	i18nModule.directive( "i18nLocale", [ "i18n", "$rootScope", function( i18n, $rootScope ) {
		return {
			restrict : "A",
			link     : function postLink( scope, element, attributes ) {
				// Observe the value provided to us and re-initialize if it changes.
				attributes.$observe( "i18nLocale", function( value ) {
					i18n.init( value );
				} );
				// Also check if a "i18nLocale" model in the scope changes its value to indicate a desired locale change.
				$rootScope.$watch( "i18nLocale", function localeChanged( newLocale, oldLocale ) {
					if( !newLocale || newLocale == oldLocale ) return;
					i18n.init( newLocale );
				} );
			}
		};
	} ] );

	/**
	 * i18n filter to be used conveniently in templates.
	 * When looking to translate just a single phrase, pass the phrase into the filter like so:
	 *
	 *   {{"My phrase"|i18n}}
	 *
	 * When you need pluralization support, pass the count into the filter, and provide the two terms as additional arguments:
	 *
	 *   {{2|i18n:"singular":"plural"}}
	 *   {{4|i18n:"%s item":"%s items"}}
	 */
	i18nModule.filter( "i18n", [
		"i18n", function( i18n ) {
			/**
			 * Check if the given input is a number.
			 * @see http://stackoverflow.com/a/1830844/259953
			 * @param n The input to check.
			 * @returns {boolean} true if the input is a number; false otherwise.
			 */
			function isNumber( n ) {
				return !isNaN( parseFloat( n ) ) && isFinite( n );
			}

			var filter = function( input ) {
				// If the input is a number, assume pluralization is requested.
				if( isNumber( input ) ) {
					return i18n.__n.apply( i18n, arguments );
				}
				return i18n.__.apply( i18n, arguments );
			};
			filter.$stateful = true;
			return filter;
		}
	] );
}());
<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var Components = require('../../components.json');
var themes = [
  'theme-default'
];
Components = Object.keys(Components);
var basepath = path.resolve(__dirname, '../../packages/');

function fileExists(filePath) {
  try {
    return fs.statSync(filePath).isFile();
  } catch (err) {
    return false;
  }
}

themes.forEach((theme) => {
  var indexContent = '@import "./base.css";\n'
  Components.forEach(function (key) {
    var fileName = key + '.css';
    indexContent += '@import "./' + fileName + '";\n';
    var filePath = path.resolve(basepath, theme, 'src', fileName);
    if (!fileExists(filePath)) {
      fs.writeFileSync(filePath, '', 'utf8');
      console.log(theme, ' 创建遗漏的 ', fileName, ' 文件');
    }
  });
  fs.writeFileSync(path.resolve(basepath, theme, 'src', 'index.css'), indexContent);
});
<commit_msg>fix eslint error<commit_after>var fs = require('fs');
var path = require('path');
var Components = require('../../components.json');
var themes = [
  'theme-default'
];
Components = Object.keys(Components);
var basepath = path.resolve(__dirname, '../../packages/');

function fileExists(filePath) {
  try {
    return fs.statSync(filePath).isFile();
  } catch (err) {
    return false;
  }
}

themes.forEach((theme) => {
  var indexContent = '@import "./base.css";\n';
  Components.forEach(function(key) {
    var fileName = key + '.css';
    indexContent += '@import "./' + fileName + '";\n';
    var filePath = path.resolve(basepath, theme, 'src', fileName);
    if (!fileExists(filePath)) {
      fs.writeFileSync(filePath, '', 'utf8');
      console.log(theme, ' 创建遗漏的 ', fileName, ' 文件');
    }
  });
  fs.writeFileSync(path.resolve(basepath, theme, 'src', 'index.css'), indexContent);
});
<|endoftext|>


<commit_before>var fs = require('fs'),
  path = require('path'),
  async = require('../support/async.min.js'),
  exec = require('child_process').exec,
  spawn = require('child_process').spawn,
  Meta = require('./metadata.js');

exports = module.exports = function Processor(command) {
  // constant for timeout checks
  this.E_PROCESSTIMEOUT = -99;

  this.saveToFile = function(targetfile, callback) {

    this.options.outputfile = targetfile;
    var self = this;

    // parse options to command
    this._prepare(function(err, meta) {
      if (err) {
        callback(null, null, err);
      } else {
        var args = self.buildFfmpegArgs(false);

        // start conversion of file using spawn
        var ffmpegProc = self._spawnProcess(args);
        if (self.options.inputstream) {
            // pump input stream to stdin
            self.options.inputstream.resume();
            self.options.inputstream.pipe(ffmpegProc.stdin);
        }

        //handle timeout if set
        var processTimer;
        if (self.options.timeout) {
          processTimer = setTimeout(function() {
            ffmpegProc.removeAllListeners('exit');
            ffmpegProc.kill('SIGKILL');
            callback(self.E_PROCESSTIMEOUT, 'timeout');
          }, self.options.timeout);
        }

        var stdout = '';
        var stderr = '';
        ffmpegProc.on('exit', function(code) {
          if (processTimer) clearTimeout(processTimer);
          // check if we have to run flvtool2 to update flash video meta data
          if (self.options._updateFlvMetadata === true) {
            // check if flvtool2 is installed
            exec('which flvtool2', function(whichErr, whichStdOut, whichStdErr) {
              if (whichStdOut != '') {
                // update metadata in flash video
                exec('flvtool2 -U ' + self.options.outputfile, function(flvtoolErr, flvtoolStdout, flvtoolStderr) {
                  callback(stdout, stderr, null);
                });
              } else {
                callback(stdout, stderr, null);
              }
            });
          } else {
            callback(stdout, stderr, null);
          }
        });

        ffmpegProc.stdout.on('data', function (data) {
          stdout += data;
        });

        ffmpegProc.stderr.on('data', function (data) {
          stderr += data;
        });
      }
    });
  };

  this.writeToStream = function(stream, callback) {
    if (!this.options._isStreamable) {
      callback(null, new Error('selected output format is not streamable'));
    } else {
      var self = this;
      // parse options to command
      this._prepare(function(err, meta) {
        if (err) {
          callback(null, err);
        } else {
          var args = self.buildFfmpegArgs(true);
          // write data to stdout
          args.push('pipe:1');

          // start conversion of file using spawn
          var ffmpegProc = self._spawnProcess(args, { customFds: [-1, stream.fd, -1] });
          if (self.options.inputstream) {
            // pump input stream to stdin
            self.options.inputstream.resume();
            self.options.inputstream.pipe(ffmpegProc.stdin);
          }

          //handle timeout if set
          var processTimer;
          if (self.options.timeout) {
            processTimer = setTimeout(function() {
              ffmpegProc.removeAllListeners('exit');
              ffmpegProc.kill('SIGKILL');
              callback(self.E_PROCESSTIMEOUT, 'timeout');
            }, self.options.timeout);
          }

          var stderr = '';

          ffmpegProc.stderr.on('data', function(data) {
            stderr += data;
          });

          ffmpegProc.stdout.on('data', function(chunk) {
          	stream.write(chunk);
          });

          ffmpegProc.on('exit', function(code, signal) {
            if (processTimer) clearTimeout(processTimer);
            // close file descriptor on outstream
            if(/http/.exec(self.options.inputfile)) {
            	callback(code, stderr);
            } else {
              var cb_ = function() {
                if (self.options.inputstream) {
                  fs.close(self.options.inputstream.fd, function() {
                    callback(code, stderr);
                  });
                }
                else {
                  callback(code, stderr);
                }
              };
              if ( !stream.fd ) {
                stream.end ? stream.end() : callback(code, "stream will not be closed");
                cb_();
              } else {
                fs.close(stream.fd, cb_);
              }
            }
          });
        }
      });
    }
  };

  this.takeScreenshot = function(config, callback) {
		if (!this.options.video.size) {
      callback(new Error("set size of thumbnails using 'withSize' method"));
    }

		var self = this;

    var input = Meta.escapedPath(this.options.inputfile);
    var output = Meta.escapedPath(config.outputfile);

		// build screenshot command
    var tnArgs = [
      '-ss', config.offset,
      '-i', input,
      '-vcodec', 'mjpeg',
      '-vframes', '1',
      '-an',
      '-f', 'rawvideo',
      '-s', self.options.video.size,
      '-y', output
    ];

		exec(process.env.FFMPEG_PATH || 'ffmpeg' + ' ' + tnArgs.join(' '), callback);
	}

  this.takeScreenshots = function(config, folder, callback) {
    var timemarks, screenshotcount;
    if (typeof config === 'object') {
      // use json object as config
      if (config.count)
        screenshotcount = config.count;
      if (config.timemarks)
        timemarks = config.timemarks;
    } else {
      // assume screenshot count as parameter
      screenshotcount = config;
      timemarks = null;
    }
    if (!this.options.video.size) {
      callback(new Error("set size of thumbnails using 'withSize' method"));
    }

    var self = this;
    // check target folder
    if (!path.existsSync(folder)) {
      fs.mkdir(folder, '0755', function(err) {
        if (err !== null) {
          callback(err);
        } else {
          _screenShotInternal(callback);
        }
      });
    } else {
      _screenShotInternal(callback);
    }

    // read metadata from file
    function _screenShotInternal(callback) {
      // get correct dimensions
      self._prepare(function(err, meta) {
        if (meta.durationsec) {
          // check if all timemarks are inside duration
          if (timemarks !== null) {
            for (var i = 0; i < timemarks.length; i++) {
              if (parseInt(timemarks[i]) > (meta.durationsec * 0.9)) {
                // remove timemark from array
                timemarks.splice(i, 1);
              }
            }
            // if there are no more timemarks around, add one at end of the file
            if (timemarks.length == 0) {
              timemarks[0] = (meta.durationsec * 0.9);
            }
          }
          // get positions for screenshots (using duration of file minus 10% to remove fade-in/fade-out)
          var secondOffset = (meta.durationsec * 0.9) / screenshotcount;
          var donecount = 0;
          var series = [];

          var i = 1;

          // use async helper function to generate all screenshots and
          // fire callback just once after work is done
          async.until(
            function() {
              return i > screenshotcount;
            },
            function(taskcallback) {
              var offset;
              if (timemarks !== null) {
                // get timemark for current iteration
                offset = timemarks[(i - 1)];
              } else {
                offset = secondOffset * i;
              }
              var target = Meta.escapedPath(folder + '/tn_' + offset + 's.jpg');
              var input = Meta.escapedPath(self.options.inputfile);

              // build screenshot command
              var tnArgs = [
                '-ss', offset,
                '-i', input,
                '-vcodec', 'mjpeg',
                '-vframes', '1',
                '-an',
                '-f', 'rawvideo',
                '-s', self.options.video.size,
                '-y', target
              ];

              i++;

              if (self.options._nice.level) {
                // execute ffmpeg through nice
                exec('nice --adjustment="' + self.options._nice.level + '" ffmpeg ' + tnArgs.join(' '), taskcallback);
              } else {
                exec(process.env.FFMPEG_PATH || 'ffmpeg' + ' ' + tnArgs.join(' '), taskcallback);
              }
            },
            function(err) {
              callback(err);
            }
          );
        } else {
          callback(new Error("meta data contains no duration, aborting screenshot creation"));
        }
      });
    }
  };

  this._spawnProcess = function(args, options) {
    var retProc = spawn(process.env.FFMPEG_PATH || 'ffmpeg', args, options);
    if (this.options._nice.level) {
      var niceLvl = (this.options._nice.level > 0 ? '+' + this.options._nice.level : this.options._nice.level);
      // renice the spawned process without waiting for callback
      exec('renice -n ' + niceLvl + ' -p ' + retProc.pid, function(err, stderr, stdout) {
        //console.log('successfully reniced process with pid ' + retProc.pid + ' to ' + niceLvl + ' niceness!');
      });
    }
    return retProc;
  };

  this.buildFfmpegArgs = function(overrideOutputCheck) {
    var args = [];

    // add startoffset and duration
    if (this.options.starttime) {
      args.push('-ss', this.options.starttime);
    }

    // add input file (if using fs mode)
    if (this.options.inputfile && !this.options.inputstream) {
      try
      {
        if(/http/.exec(this.options.inputfile)) {
          args.push('-i', this.options.inputfile.replace(' ', '%20'));
        } else {
          var fstats = fs.statSync(this.options.inputfile);
          if (fstats.isFile()) {
            // fix for spawn call with path containing spaces
            args.push('-i', this.options.inputfile.replace(' ', '\ '));
          } else {
            throw new Error('input file is not readable');
          }
        }
      } catch (err) {
        // handle error somehow
        throw err;
      }
    // check for input stream
    } else if (this.options.inputstream) {
      // push args to make ffmpeg read from stdin
      args.push('-i', '-');
    }

    if (this.options.duration) {
      args.push('-t', this.options.duration);
    }

    // add format
    if (this.options.format) {
      args.push('-f', this.options.format);
    }

    // add video options
    if (this.options.video.bitrate) {
      args.push('-b', this.options.video.bitrate + 'k');
      if (this.options._useConstantVideoBitrate) {
        // add parameters to ensure constant bitrate encoding
        args.push('-maxrate', this.options.video.bitrate + 'k');
        args.push('-minrate', this.options.video.bitrate + 'k');
        args.push('-bufsize', '3M');
      }
    } else {
      // use same quality for output as used in input
      args.push('-sameq');
    }
    if (this.options.video.codec) {
      args.push('-vcodec', this.options.video.codec);
    }
    if (this.options.video.fps) {
      args.push('-keyint_min', this.options.video.fps);
    }
    if (this.options.video.aspect) {
      args.push('-aspect', this.options.video.aspect);
    }

    // add video options
    if (this.options.audio.bitrate) {
      args.push('-ab', this.options.audio.bitrate + 'k');
    }
    if (this.options.audio.channels) {
      args.push('-ac', this.options.audio.channels);
    }
    if (this.options.audio.codec) {
      args.push('-acodec', this.options.audio.codec);
    }
    if (this.options.audio.frequency) {
      args.push('-ar', this.options.audio.frequency);
    }

    // add additional options
    if (this.options.additional) {
      if (this.options.additional.length > 0) {
        this.options.additional.forEach(function(el) {
          args.push(el);
        });
      }
    }
    if (this.options.video.pad) {
      // we have padding arguments, push
      args.push('-vf');
      args.push('pad=' + this.options.video.pad.w +
        ':' + this.options.video.pad.h +
        ':' + this.options.video.pad.x +
        ':' + this.options.video.pad.y +
        ':' + this.options.video.padcolor);
    }

    // add size and output file
    if (this.options.video.size) {
      args.push('-s', this.options.video.size);
    }

    if (this.options.outputfile) {
      args.push('-y', this.options.outputfile.replace(' ', '\ '));
    } else {
      if (!overrideOutputCheck) {
        throw new Error("no outputfile specified");
      }
    }

    return args;
  };
};
<commit_msg>fixed customFd error messages<commit_after>var fs = require('fs'),
  path = require('path'),
  async = require('../support/async.min.js'),
  exec = require('child_process').exec,
  spawn = require('child_process').spawn,
  Meta = require('./metadata.js');

exports = module.exports = function Processor(command) {
  // constant for timeout checks
  this.E_PROCESSTIMEOUT = -99;

  this.saveToFile = function(targetfile, callback) {

    this.options.outputfile = targetfile;
    var self = this;

    // parse options to command
    this._prepare(function(err, meta) {
      if (err) {
        callback(null, null, err);
      } else {
        var args = self.buildFfmpegArgs(false);

        // start conversion of file using spawn
        var ffmpegProc = self._spawnProcess(args);
        if (self.options.inputstream) {
            // pump input stream to stdin
            self.options.inputstream.resume();
            self.options.inputstream.pipe(ffmpegProc.stdin);
        }

        //handle timeout if set
        var processTimer;
        if (self.options.timeout) {
          processTimer = setTimeout(function() {
            ffmpegProc.removeAllListeners('exit');
            ffmpegProc.kill('SIGKILL');
            callback(self.E_PROCESSTIMEOUT, 'timeout');
          }, self.options.timeout);
        }

        var stdout = '';
        var stderr = '';
        ffmpegProc.on('exit', function(code) {
          if (processTimer) clearTimeout(processTimer);
          // check if we have to run flvtool2 to update flash video meta data
          if (self.options._updateFlvMetadata === true) {
            // check if flvtool2 is installed
            exec('which flvtool2', function(whichErr, whichStdOut, whichStdErr) {
              if (whichStdOut != '') {
                // update metadata in flash video
                exec('flvtool2 -U ' + self.options.outputfile, function(flvtoolErr, flvtoolStdout, flvtoolStderr) {
                  callback(stdout, stderr, null);
                });
              } else {
                callback(stdout, stderr, null);
              }
            });
          } else {
            callback(stdout, stderr, null);
          }
        });

        ffmpegProc.stdout.on('data', function (data) {
          stdout += data;
        });

        ffmpegProc.stderr.on('data', function (data) {
          stderr += data;
        });
      }
    });
  };

  this.writeToStream = function(stream, callback) {
    if (!this.options._isStreamable) {
      callback(null, new Error('selected output format is not streamable'));
    } else {
      var self = this;
      // parse options to command
      this._prepare(function(err, meta) {
        if (err) {
          callback(null, err);
        } else {
          var args = self.buildFfmpegArgs(true);
          // write data to stdout
          args.push('pipe:1');

          // start conversion of file using spawn
          var ffmpegProc = self._spawnProcess(args);

          if (self.options.inputstream) {
            // pump input stream to stdin
            self.options.inputstream.resume();
            self.options.inputstream.pipe(ffmpegProc.stdin);
          }

          //handle timeout if set
          var processTimer;
          if (self.options.timeout) {
            processTimer = setTimeout(function() {
              ffmpegProc.removeAllListeners('exit');
              ffmpegProc.kill('SIGKILL');
              callback(self.E_PROCESSTIMEOUT, 'timeout');
            }, self.options.timeout);
          }

          var stderr = '';

          ffmpegProc.stderr.on('data', function(data) {
            stderr += data;
          });

          ffmpegProc.stdout.on('data', function(chunk) {
          	stream.write(chunk);
          });

          ffmpegProc.on('exit', function(code, signal) {
            if (processTimer) clearTimeout(processTimer);
            // close file descriptor on outstream
            if(/http/.exec(self.options.inputfile)) {
            	callback(code, stderr);
            } else {
              var cb_ = function() {
                if (self.options.inputstream) {
                  fs.close(self.options.inputstream.fd, function() {
                    callback(code, stderr);
                  });
                }
                else {
                  callback(code, stderr);
                }
              };
              if ( !stream.fd ) {
                stream.end ? stream.end() : callback(code, "stream will not be closed");
                cb_();
              } else {
                fs.close(stream.fd, cb_);
              }
            }
          });
        }
      });
    }
  };

  this.takeScreenshot = function(config, callback) {
		if (!this.options.video.size) {
      callback(new Error("set size of thumbnails using 'withSize' method"));
    }

		var self = this;

    var input = Meta.escapedPath(this.options.inputfile);
    var output = Meta.escapedPath(config.outputfile);

		// build screenshot command
    var tnArgs = [
      '-ss', config.offset,
      '-i', input,
      '-vcodec', 'mjpeg',
      '-vframes', '1',
      '-an',
      '-f', 'rawvideo',
      '-s', self.options.video.size,
      '-y', output
    ];

		exec(process.env.FFMPEG_PATH || 'ffmpeg' + ' ' + tnArgs.join(' '), callback);
	}

  this.takeScreenshots = function(config, folder, callback) {
    var timemarks, screenshotcount;
    if (typeof config === 'object') {
      // use json object as config
      if (config.count)
        screenshotcount = config.count;
      if (config.timemarks)
        timemarks = config.timemarks;
    } else {
      // assume screenshot count as parameter
      screenshotcount = config;
      timemarks = null;
    }
    if (!this.options.video.size) {
      callback(new Error("set size of thumbnails using 'withSize' method"));
    }

    var self = this;
    // check target folder
    if (!fs.existsSync(folder)) {
      fs.mkdir(folder, '0755', function(err) {
        if (err !== null) {
          callback(err);
        } else {
          _screenShotInternal(callback);
        }
      });
    } else {
      _screenShotInternal(callback);
    }

    // read metadata from file
    function _screenShotInternal(callback) {
      // get correct dimensions
      self._prepare(function(err, meta) {
        if (meta.durationsec) {
          // check if all timemarks are inside duration
          if (timemarks !== null) {
            for (var i = 0; i < timemarks.length; i++) {
              if (parseInt(timemarks[i]) > (meta.durationsec * 0.9)) {
                // remove timemark from array
                timemarks.splice(i, 1);
              }
            }
            // if there are no more timemarks around, add one at end of the file
            if (timemarks.length == 0) {
              timemarks[0] = (meta.durationsec * 0.9);
            }
          }
          // get positions for screenshots (using duration of file minus 10% to remove fade-in/fade-out)
          var secondOffset = (meta.durationsec * 0.9) / screenshotcount;
          var donecount = 0;
          var series = [];

          var i = 1;

          // use async helper function to generate all screenshots and
          // fire callback just once after work is done
          async.until(
            function() {
              return i > screenshotcount;
            },
            function(taskcallback) {
              var offset;
              if (timemarks !== null) {
                // get timemark for current iteration
                offset = timemarks[(i - 1)];
              } else {
                offset = secondOffset * i;
              }
              var target = Meta.escapedPath(folder + '/tn_' + offset + 's.jpg');
              var input = Meta.escapedPath(self.options.inputfile);

              // build screenshot command
              var tnArgs = [
                '-ss', offset,
                '-i', input,
                '-vcodec', 'mjpeg',
                '-vframes', '1',
                '-an',
                '-f', 'rawvideo',
                '-s', self.options.video.size,
                '-y', target
              ];

              i++;

              if (self.options._nice.level) {
                // execute ffmpeg through nice
                exec('nice -n="' + self.options._nice.level + '" ffmpeg ' + tnArgs.join(' '), taskcallback);
              } else {
                exec(process.env.FFMPEG_PATH || 'ffmpeg' + ' ' + tnArgs.join(' '), taskcallback);
              }
            },
            function(err) {
              callback(err);
            }
          );
        } else {
          callback(new Error("meta data contains no duration, aborting screenshot creation"));
        }
      });
    }
  };

  this._spawnProcess = function(args, options) {
    var retProc = spawn(process.env.FFMPEG_PATH || 'ffmpeg', args, options);
    if (this.options._nice.level) {
      var niceLvl = (this.options._nice.level > 0 ? '+' + this.options._nice.level : this.options._nice.level);
      // renice the spawned process without waiting for callback
      exec('renice -n ' + niceLvl + ' -p ' + retProc.pid, function(err, stderr, stdout) {
        //console.log('successfully reniced process with pid ' + retProc.pid + ' to ' + niceLvl + ' niceness!');
      });
    }
    return retProc;
  };

  this.buildFfmpegArgs = function(overrideOutputCheck) {
    var args = [];

    // add startoffset and duration
    if (this.options.starttime) {
      args.push('-ss', this.options.starttime);
    }

    // add input file (if using fs mode)
    if (this.options.inputfile && !this.options.inputstream) {
      try
      {
        if(/http/.exec(this.options.inputfile)) {
          args.push('-i', this.options.inputfile.replace(' ', '%20'));
        } else {
          var fstats = fs.statSync(this.options.inputfile);
          if (fstats.isFile()) {
            // fix for spawn call with path containing spaces
            args.push('-i', this.options.inputfile.replace(' ', '\ '));
          } else {
            throw new Error('input file is not readable');
          }
        }
      } catch (err) {
        // handle error somehow
        throw err;
      }
    // check for input stream
    } else if (this.options.inputstream) {
      // push args to make ffmpeg read from stdin
      args.push('-i', '-');
    }

    if (this.options.duration) {
      args.push('-t', this.options.duration);
    }

    // add format
    if (this.options.format) {
      args.push('-f', this.options.format);
    }

    // add video options
    if (this.options.video.bitrate) {
      args.push('-b', this.options.video.bitrate + 'k');
      if (this.options._useConstantVideoBitrate) {
        // add parameters to ensure constant bitrate encoding
        args.push('-maxrate', this.options.video.bitrate + 'k');
        args.push('-minrate', this.options.video.bitrate + 'k');
        args.push('-bufsize', '3M');
      }
    } else {
      // use same quality for output as used in input
      args.push('-sameq');
    }
    if (this.options.video.codec) {
      args.push('-vcodec', this.options.video.codec);
    }
    if (this.options.video.fps) {
      args.push('-keyint_min', this.options.video.fps);
    }
    if (this.options.video.aspect) {
      args.push('-aspect', this.options.video.aspect);
    }

    // add video options
    if (this.options.audio.bitrate) {
      args.push('-ab', this.options.audio.bitrate + 'k');
    }
    if (this.options.audio.channels) {
      args.push('-ac', this.options.audio.channels);
    }
    if (this.options.audio.codec) {
      args.push('-acodec', this.options.audio.codec);
    }
    if (this.options.audio.frequency) {
      args.push('-ar', this.options.audio.frequency);
    }

    // add additional options
    if (this.options.additional) {
      if (this.options.additional.length > 0) {
        this.options.additional.forEach(function(el) {
          args.push(el);
        });
      }
    }
    if (this.options.video.pad) {
      // we have padding arguments, push
      args.push('-vf');
      args.push('pad=' + this.options.video.pad.w +
        ':' + this.options.video.pad.h +
        ':' + this.options.video.pad.x +
        ':' + this.options.video.pad.y +
        ':' + this.options.video.padcolor);
    }

    // add size and output file
    if (this.options.video.size) {
      args.push('-s', this.options.video.size);
    }

    if (this.options.outputfile) {
      args.push('-y', this.options.outputfile.replace(' ', '\ '));
    } else {
      if (!overrideOutputCheck) {
        throw new Error("no outputfile specified");
      }
    }

    return args;
  };
};
<|endoftext|>


<commit_before>/*!

   Viewport autoplay  plugin for Flowplayer HTML5

   Copyright (c) 2016-2017, Flowplayer Drive Oy

   Released under the MIT License:
   http://www.opensource.org/licenses/mit-license.php

   Requires Flowplayer HTML5 version 7.x or greater
   $GIT_DESC$

*/
(function() {

  var requestAnimationFrame = window.requestAnimationFrame || setTimeout;

  var extension = function(flowplayer) {
    var common = flowplayer.common;
    flowplayer(function(api, root) {
      if (!api.conf.autoplay || api.conf.splash) return;
      api.conf.autoplay = false;
      var scrollPaused = true;

      if (api.conf.muted && !flowplayer.support.mutedAutoplay) {
        common.addClass(root, 'is-muted-autoplaying');
        var ap = document.createElement('div');
        ap.className = 'fp-autoplay-overlay';
        ap.innerHTML = 'Click to unmute.. ';
        root.appendChild(ap);

        ap.addEventListener('click', function(ev) {
          if (common.hasClass(ev.target, 'pause')) {
            ev.preventDefault();
            api.toggle();
          } else {
            ev.stopPropagation();
            ev.preventDefault();
            api.mute(false);
            common.removeClass(root, 'is-muted-autoplaying');
            if (flowplayer.support.mutedAutoplay) flowplayer.common.find('.fp-engine', root)[0].muted = false;
            root.removeChild(ap);
          }
        });
      }

      function startPlaybackIfInViewport() {
        if (isElementInViewport(root)) {
          if (flowplayer.support.mutedAutoplay && !api.video.time) flowplayer.common.find('.fp-engine', root)[0].muted = true;
          if (scrollPaused) {
            api.one('resume', function () {scrollPaused = false;});
            api.resume();
          }
        }
        else if (api.playing) {
          api.one('pause', function () {scrollPaused = true;});
          api.pause();
        }
      }

      api.on('ready', startPlaybackIfInViewport);

      flowplayer.bean.on(window, 'scroll.autoplay', function() {
        requestAnimationFrame(startPlaybackIfInViewport);
      });
    });

  };

  function isElementInViewport(el) {
    var rect = el.getBoundingClientRect();
    var offset = rect.height * 0.8;
    return (
      rect.top + offset >= 0 &&
      rect.left >= 0 &&
      rect.bottom - offset <= (window.innerHeight || document.documentElement.clientHeight)  &&
      rect.right <= (window.innerWidth || document.documentElement.clientWidth)
    );
  }

  if (typeof module === 'object' && module.exports) module.exports = extension;
  else if (typeof window.flowplayer === 'function') extension(window.flowplayer);

})();
<commit_msg>Avoid autoplay of players scrolled over on page load (#9)<commit_after>/*!

   Viewport autoplay  plugin for Flowplayer HTML5

   Copyright (c) 2016-2017, Flowplayer Drive Oy

   Released under the MIT License:
   http://www.opensource.org/licenses/mit-license.php

   Requires Flowplayer HTML5 version 7.x or greater
   $GIT_DESC$

*/
(function() {

  var requestAnimationFrame = window.requestAnimationFrame || setTimeout;

  var extension = function(flowplayer) {
    var common = flowplayer.common;
    flowplayer(function(api, root) {
      if (!api.conf.autoplay || api.conf.splash) return;
      api.conf.autoplay = false;
      var scrollPaused = true;

      if (api.conf.muted && !flowplayer.support.mutedAutoplay) {
        common.addClass(root, 'is-muted-autoplaying');
        var ap = document.createElement('div');
        ap.className = 'fp-autoplay-overlay';
        ap.innerHTML = 'Click to unmute.. ';
        root.appendChild(ap);

        ap.addEventListener('click', function(ev) {
          if (common.hasClass(ev.target, 'pause')) {
            ev.preventDefault();
            api.toggle();
          } else {
            ev.stopPropagation();
            ev.preventDefault();
            api.mute(false);
            common.removeClass(root, 'is-muted-autoplaying');
            if (flowplayer.support.mutedAutoplay) flowplayer.common.find('.fp-engine', root)[0].muted = false;
            root.removeChild(ap);
          }
        });
      }

      function startPlaybackIfInViewport() {
        if (isElementInViewport(root)) {
          if (flowplayer.support.mutedAutoplay && !api.video.time) flowplayer.common.find('.fp-engine', root)[0].muted = true;
          if (scrollPaused) {
            api.one('resume', function () {scrollPaused = false;});
            api.resume();
          }
        }
        else {
          // issue #9
          if (api.playing) {
            api.one('pause', function () {scrollPaused = true;});
          }
          api.pause();
        }
      }

      api.on('ready', startPlaybackIfInViewport);

      flowplayer.bean.on(window, 'scroll.autoplay', function() {
        requestAnimationFrame(startPlaybackIfInViewport);
      });
    });

  };

  function isElementInViewport(el) {
    var rect = el.getBoundingClientRect();
    var offset = rect.height * 0.8;
    return (
      rect.top + offset >= 0 &&
      rect.left >= 0 &&
      rect.bottom - offset <= (window.innerHeight || document.documentElement.clientHeight)  &&
      rect.right <= (window.innerWidth || document.documentElement.clientWidth)
    );
  }

  if (typeof module === 'object' && module.exports) module.exports = extension;
  else if (typeof window.flowplayer === 'function') extension(window.flowplayer);

})();
<|endoftext|>


<commit_before>// TODO this should support passing in projection strings in many formats, including preconstructed Proj4 objects

var Proj4 = require('proj4js');

var originShift = 2 * Math.PI * 6378137 / 2.0; //20037508.342789244

// Credit for the math: http://www.maptiler.org/google-maps-coordinates-tile-bounds-projection/
var util = {
  pixelsToMeters: function(x, y, zoom, tileSize) {
    var mx, my;
    var tileSize = tileSize || 256;
    // meters per pixel at zoom 0
    var initialResolution = 2 * Math.PI * 6378137 / tileSize;
    //Resolution (meters/pixel) for given zoom level (measured at Equator)"
    var res = initialResolution / Math.pow(2,zoom);
    // return (2 * math.pi * 6378137) / (self.tileSize * 2**zoom)
    mx = x * res - originShift;
    my = y * res - originShift;
    return [mx, my];
  },
  metersToLatLon: function(x, y) {
    //Converts XY point from Spherical Mercator EPSG:900913 to lat/lon in WGS84 Datum"
    var lon, lat;
    lon = (x / originShift) * 180.0;
    lat = (y / originShift) * 180.0;
    lat = 180 / Math.pi * (2 * Math.atan( Math.exp( lat * Math.pi / 180.0)) - Math.pi / 2.0);
    return [lon, lat];
  },
  tileToMeters: function(x, y, zoom, tileSize){
    var tileSize = tileSize || 256;
    y = (Math.pow(2,zoom) - 1) - y; // TMS to Google tile scheme
    var min = util.pixelsToMeters(x*tileSize, y*tileSize, zoom);
    var max = util.pixelsToMeters((x+1)*tileSize, (y+1)*tileSize, zoom);
    return [min[0], min[1], max[0], max[1]];
  }
}
var project = {

  'FeatureCollection': function(inProjection, outProjection, fc) {
    fc.features.forEach(project.Feature.bind(null, inProjection, outProjection));
    return fc;
  },
  'Feature': function(inProjection, outProjection, f) {
    project[f.geometry.type](inProjection, outProjection, f.geometry.coordinates);
    return f;
  },
  'MultiPolygon': function(inProjection, outProjection, mp) {
    mp.forEach(project.Polygon.bind(null, inProjection, outProjection));
    return mp;
  },
  'Polygon': function(inProjection, outProjection, p) {
    p.forEach(project.LineString.bind(null, inProjection, outProjection));
    return p;
  },
  'MultiLineString': function(inProjection, outProjection, ml) {
    ml.forEach(project.LineString.bind(null, inProjection, outProjection));
    return ml;
  },
  'LineString': function(inProjection, outProjection, l) {
    l.forEach(project.Point.bind(null, inProjection, outProjection));
    return l;
  },
  'MultiPoint': function(inProjection, outProjection, mp) {
    mp.forEach(project.Point.bind(null, inProjection, outProjection));
    return mp;
  },
  'Point': function(inProjection, outProjection, c) {
    if (inProjection && outProjection) {
      // TODO: only do this if typeof inProj or outProj is string. Or do it once earlier in the process.
      var from = new Proj4.Proj(inProjection);
      var to = new Proj4.Proj(outProjection);
      var point = new Proj4.Point(c);
      Proj4.transform(from, to, point);
      c[0] = point.x;
      c[1] = point.y;
    } else {
      c[0] = 256.0 * (c[0] + 180) / 360.0;
      c[1] = 256.0 - 256.0 * (Math.PI + Math.log(Math.tan(Math.PI/4+c[1]*(Math.PI/180)/2))) / (2*Math.PI);
    }
    return c;
  }
};

// TODO: cleanup interface
module.exports.util = util;
module.exports.project = project;

// {};
// this is sexy but doesn't work
/*Object.keys(project).forEach(function(featureType) {
  exports.project[featureType] = function(inProjection, outProjection, feature) {
    var from = inProjection && new Proj4.Proj(inProjection),
  to = outProjection && new Proj4.Proj(outProjection);

return project[featureType](null, null, feature);
  };
});
*/<commit_msg>Modified projector to not project points in place, allows static example to reproject without restarting server<commit_after>// TODO this should support passing in projection strings in many formats, including preconstructed Proj4 objects

var Proj4 = require('proj4js');
var __ = require('lodash');

var originShift = 2 * Math.PI * 6378137 / 2.0; //20037508.342789244

// Credit for the math: http://www.maptiler.org/google-maps-coordinates-tile-bounds-projection/
var util = {
  pixelsToMeters: function(x, y, zoom, tileSize) {
    var mx, my;
    var tileSize = tileSize || 256;
    // meters per pixel at zoom 0
    var initialResolution = 2 * Math.PI * 6378137 / tileSize;
    //Resolution (meters/pixel) for given zoom level (measured at Equator)"
    var res = initialResolution / Math.pow(2,zoom);
    // return (2 * math.pi * 6378137) / (self.tileSize * 2**zoom)
    mx = x * res - originShift;
    my = y * res - originShift;
    return [mx, my];
  },
  metersToLatLon: function(x, y) {
    //Converts XY point from Spherical Mercator EPSG:900913 to lat/lon in WGS84 Datum"
    var lon, lat;
    lon = (x / originShift) * 180.0;
    lat = (y / originShift) * 180.0;
    lat = 180 / Math.pi * (2 * Math.atan( Math.exp( lat * Math.pi / 180.0)) - Math.pi / 2.0);
    return [lon, lat];
  },
  tileToMeters: function(x, y, zoom, tileSize){
    var tileSize = tileSize || 256;
    y = (Math.pow(2,zoom) - 1) - y; // TMS to Google tile scheme
    var min = util.pixelsToMeters(x*tileSize, y*tileSize, zoom);
    var max = util.pixelsToMeters((x+1)*tileSize, (y+1)*tileSize, zoom);
    return [min[0], min[1], max[0], max[1]];
  }
}
var project = {

  'FeatureCollection': function(inProjection, outProjection, fc) {
    var from = new Proj4.Proj(inProjection);
    var to = new Proj4.Proj(outProjection);
    var _fc = __.clone(fc, true);
    console.log(_fc.features[0].geometry.coordinates[0]);
    _fc.features.forEach(project.Feature.bind(null, from, to));
    console.log(_fc.features[0].geometry.coordinates[0]);
    return _fc;
  },
  'Feature': function(inProjection, outProjection, f) {
    project[f.geometry.type](inProjection, outProjection, f.geometry.coordinates);
    return f;
  },
  'MultiPolygon': function(inProjection, outProjection, mp) {
    mp.forEach(project.Polygon.bind(null, inProjection, outProjection));
    return mp;
  },
  'Polygon': function(inProjection, outProjection, p) {
    p.forEach(project.LineString.bind(null, inProjection, outProjection));
    return p;
  },
  'MultiLineString': function(inProjection, outProjection, ml) {
    ml.forEach(project.LineString.bind(null, inProjection, outProjection));
    return ml;
  },
  'LineString': function(inProjection, outProjection, l) {
    l.forEach(project.Point.bind(null, inProjection, outProjection));
    return l;
  },
  'MultiPoint': function(inProjection, outProjection, mp) {
    mp.forEach(project.Point.bind(null, inProjection, outProjection));
    return mp;
  },
  'Point': function(inProjection, outProjection, c) {
    if (inProjection && outProjection) {
      var from, to;
      // TODO: only do this if typeof inProj or outProj is string. Or do it once earlier in the process.
      if (inProjection instanceof Proj4.Proj){
        from = inProjection;
      } else {
        from = new Proj4.Proj(inProjection);
      }

      if (outProjection instanceof Proj4.Proj){
        to = outProjection;
      } else {
        to = new Proj4.Proj(outProjection);
      }

      //while (!from.readyToUse || !to.readyToUse) {
      //  console.log("Projections not ready");
      //}

      var point = new Proj4.Point(c);
      Proj4.transform(from, to, point);
      c[0] = point.x;
      c[1] = point.y;
//    } else {
//      p[0] = 256.0 * (c[0] + 180) / 360.0;
//      p[1] = 256.0 - 256.0 * (Math.PI + Math.log(Math.tan(Math.PI/4+c[1]*(Math.PI/180)/2))) / (2*Math.PI);
    }
    return c;
  }
};

// TODO: cleanup interface
module.exports.util = util;
module.exports.project = project;

// {};
// this is sexy but doesn't work
/*Object.keys(project).forEach(function(featureType) {
  exports.project[featureType] = function(inProjection, outProjection, feature) {
  var from = inProjection && new Proj4.Proj(inProjection),
  to = outProjection && new Proj4.Proj(outProjection);

  return project[featureType](null, null, feature);
  };
  });
  */
<|endoftext|>


<commit_before>// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'

// Load external libs
import axios from 'axios'
import lodash from 'lodash'
import feather from 'feather-icons'
import VueHighlightJS from 'vue-highlightjs'
import VueFeatherIcon from 'vue-feather-icon'
Vue.prototype.$http = axios.create()
Vue.prototype._ = lodash
Vue.prototype.feather = feather
Vue.use(VueHighlightJS)
Vue.prototype.beautify = require('js-beautify').html
Vue.use(VueFeatherIcon)

// Components
import CodePreview from './components/CodePreview'
Vue.component('code-preview', CodePreview)

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  template: '<App/>',
  components: { App }
})
<commit_msg>Small fix, removing vue wrapper component for feather-icons<commit_after>// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'

// Load external libs
import axios from 'axios'
import lodash from 'lodash'
import feather from 'feather-icons'
import VueHighlightJS from 'vue-highlightjs'
Vue.prototype.$http = axios.create()
Vue.prototype._ = lodash
Vue.prototype.feather = feather
Vue.use(VueHighlightJS)
Vue.prototype.beautify = require('js-beautify').html

// Components
import CodePreview from './components/CodePreview'
Vue.component('code-preview', CodePreview)

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  template: '<App/>',
  components: { App }
})
<|endoftext|>


<commit_before>module.exports = {
    '1': {
        text: 'What kind of construction permit do you need to submit?',
        answers: {
            'Commercial': { next: 2 },
            'Residential': { next: 3 }
        }
    },

    '3': {
        text: 'Is it one of the following projects

Replacing windows and/or exterior doors of the same size and same location

Adding/Removing siding or brick

Repairing a roof to the extent of replacing decking boards/fascia

Repairing foundation without increasing impervious cover

Roof mounted solar panels

Remove/Repair drywall in excess of 32 sq. ft.

Adding/Replacing insulation

Tub/Shower Conversions

',
        answers: {
            'yes': { next: 4 },
            'no': { next: 2 }
        }
    },

    '4': {
        text: "Will this project involve any structural members or increase square footage of structure?",
        answers: {
            'yes': { next: 2 },
            'no': { next: 5 }
        },
    },

    '5': {
        message: 'You have qualified for an express permit',
        text: "Are you in a historic district?",
        answers: {
            'yes': { next: 6, checklist: 'Please schedule an appointment with the Historic District' },
            'no': { next: 6 }
        }
    },

    '6': {
        text: 'Are you in an airport overlay zone?',
        answers: {
            'yes': { next: 7, checklist: 'Please schedule an appointment with the Aviation Department' },
            'no': { next: 7 }
        }
    },

    '7': {
        text: 'Are you within 150 feet of a floodplain?',
        answers: {
            'yes': { next: 8, checklist: 'Please bring a FEMA elevation certificate form with your application' },
            'no': { next: 8 }
        }
    },

    '8': {
        text: "Do you have expired permits?",
        answers: {
            'yes': { next: 9 },
            'no': { next: 11 }
        }
    },

    '9': {
        text: 'Does the expired permit work qualify for the express permit?',
        answers: {
            'yes': { next: 12, checklist: 'Add the expired permit work to the current permit' },
            'no': { next: 12, checklist: 'Bring an Acknowledgement of Expired Permit form with your application' }
        }
    },

    '12': {
        permitId:1
    }

};<commit_msg>Use proper casing in questions json<commit_after>module.exports = {
    '1': {
        text: 'What kind of construction permit do you need to submit?',
        answers: {
            'Commercial': { next: 2 },
            'Residential': { next: 3 }
        }
    },

    '3': {
        text: 'Is it one of the following projects

Replacing windows and/or exterior doors of the same size and same location

Adding/Removing siding or brick

Repairing a roof to the extent of replacing decking boards/fascia

Repairing foundation without increasing impervious cover

Roof mounted solar panels

Remove/Repair drywall in excess of 32 sq. ft.

Adding/Replacing insulation

Tub/Shower Conversions

',
        answers: {
            'Yes': { next: 4 },
            'No': { next: 2 }
        }
    },

    '4': {
        text: "Will this project involve any structural members or increase square footage of structure?",
        answers: {
            'Yes': { next: 2 },
            'No': { next: 5 }
        },
    },

    '5': {
        message: 'You have qualified for an express permit',
        text: "Are you in a historic district?",
        answers: {
            'Yes': { next: 6, checklist: 'Please schedule an appointment with the Historic District' },
            'No': { next: 6 }
        }
    },

    '6': {
        text: 'Are you in an airport overlay zone?',
        answers: {
            'Yes': { next: 7, checklist: 'Please schedule an appointment with the Aviation Department' },
            'No': { next: 7 }
        }
    },

    '7': {
        text: 'Are you within 150 feet of a floodplain?',
        answers: {
            'Yes': { next: 8, checklist: 'Please bring a FEMA elevation certificate form with your application' },
            'No': { next: 8 }
        }
    },

    '8': {
        text: "Do you have expired permits?",
        answers: {
            'Yes': { next: 9 },
            'No': { next: 11 }
        }
    },

    '9': {
        text: 'Does the expired permit work qualify for the express permit?',
        answers: {
            'Yes': { next: 12, checklist: 'Add the expired permit work to the current permit' },
            'No': { next: 12, checklist: 'Bring an Acknowledgement of Expired Permit form with your application' }
        }
    },

    '12': {
        permitId:1
    }

};<|endoftext|>