<commit_before>/*
 * The MIT License (MIT)
 * Copyright (c) 2017 Heat Ledger Ltd
 *
 * 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.
 * */

require('es6-promise').polyfill(); /* usemin requires this */
var gulp = require('gulp');
var util = require('gulp-util');
var chalk = require('chalk');

var PATHS = {
  src: [
    'src/*.ts',
    'src/**/*.ts'
  ],
  heatdir: "../heatledger/build/install/heatledger"
};

gulp.task('clean', function () {
  var del = require('del');
  return del(['dist']);
});

gulp.task('ts2js', function () {
  var typescript = require('gulp-typescript');
  var sourcemaps = require('gulp-sourcemaps');
  var tscConfig = require('./tsconfig.json');
  var extend = require('util')._extend;
  var concat = require('gulp-concat');

  return gulp.src(PATHS.src)
    .pipe(sourcemaps.init())
    .pipe(typescript(extend(tscConfig.compilerOptions)))
    .pipe(concat('index.js'))
    .pipe(sourcemaps.write('../dist'))
    .pipe(gulp.dest('dist'));
});

/**
 * To test a microservice we write a javascript test script which is passed
 * to the heatledger binary as its -run paramater.
 * Upon seeing the -run parameter the heatledger server will after loading
 * execute this test script which in turns performs the test.
 *
 * Usage:
 *
 *    `gulp -run "script.to.execute()" --heatdir /foo/bar --verbose`
 *
 * Parameters:
 *
 *    --heatdir     Absolute path to heat installation directory.
 *                  Note: The installation directory folder layout looks like this
 *
 *                    - heatledger            <-- This is the installation directory
 *                      - bin
 *                      - blockchain
 *                      - conf
 *                      - lib
 *                      etc...
 *
 *    --run         The script to execute, must be surrounded in quotes ("..")
 *
 *    --verbose     When provided will also include all console output from heat server,
 *                  otherwise only console output from your script is shown.
 */
gulp.task('test', ['build'], function (cb) {
  var argv = require('yargs').argv;
  var exec = require('child_process').exec;
  var spawn = require('child_process').spawn;
  var path = require('path');

  var scriptsDir = path.join(__dirname, 'dist');
  var isWin = /^win/.test(process.platform);
  var heatbin = isWin ? "bin\heatledger.bat" : "bin/heatledger";
  var heatdir = argv.heatdir || PATHS.heatdir;
  var sourcedir = path.join(__dirname, 'src');
  var server = spawn(heatbin, ["-path", scriptsDir, "-run", argv.run, "-sourcedir", sourcedir], { cwd: heatdir });

  function logVerbose(msg) {
    if (!msg || msg.trim().length == 0) return;
    var lines = msg.split(/(\r?\n)/g);
    for (var i=0; i<lines.length; i++) {
      if (lines[i].match(/\S/)) {
        util.log(lines[i]);
      }
    }
  }

  function logScript(msg) {
    if (!msg || msg.trim().length == 0) return;
    var lines = msg.split(/(\r?\n)/g);
    for (var i=0; i<lines.length; i++) {
      if (lines[i].match(/\S/)) {
        // matches 2017-04-30 21:37:18 [main] INFO  com.heatledger.HeatProperties - heat.replicatorEnabled = "false"
        var parts = /\S+\s+\S+\s+\[.*\]\s+\S+\s+(\S+)/.exec(lines[i]);
        if (parts) {
          var className = parts[1];
          if (className.trim() == "<script>") {
            var cleaned = lines[i].replace(/(^.*<script>\s+-)/,chalk.red("<script>"));
            util.log(cleaned);
          }
        }
        // matches 21:32:33,278 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
        else if (lines[i].match(/^.*\|-\S+\s+in\s+ch.qos.logback/)) {
          continue;
        }
        else {
          util.log(lines[i]);
        }
      }
    }
  }

  var log = argv.verbose ? logVerbose : logScript;

  server.stdout.on('data', (data) => { log(data+"") });
  server.stderr.on('data', (data) => { log(data+"") });
});

gulp.task('build', ['clean','ts2js']);
gulp.task('default', ['build']);
<commit_msg>Gulp build and test scripts<commit_after>/*
 * The MIT License (MIT)
 * Copyright (c) 2017 Heat Ledger Ltd
 *
 * 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.
 * */

require('es6-promise').polyfill(); /* usemin requires this */
var gulp = require('gulp');
var util = require('gulp-util');
var chalk = require('chalk');
var _ = require('underscore');
var heatledger;
try {
  heatledger = require('./heatledger.json');
} catch (e) {}

// There are three 'modes' in which we can run and test our microservices
//
//    * --mode main     Will start and connect heatledger on the main network
//    * --mode test     Will start and connect heatledger on the test network
//    * --mode fake     Will start heatledger on a fake one-time blockchain,
//                      in this mode you must use the heat.driver to manually
//                      generate blocks.
//                      You have access to a funded account with the secretphrase
//                      'fake' (without quotes) which has 10,000,000 fake HEAT.
//
// When no mode is provided fake mode is assumed.
var modes = {
  main: {
    "heat.replicatorEnabled": "true",
    "heat.enableAPIServer": "true"
  },
  test: {
    "heat.replicatorEnabled": "true",
    "heat.enableAPIServer": "true",
    "heat.isTestnet": "true",
    "heat.numberOfForkConfirmations": "0"
  },
  fake: {
    "heat.replicatorEnabled": "true",
    "heat.enableAPIServer": "true",
    "heat.isTestnet": "true",
    "heat.blockchainDir": "microservice-test",
    "heat.isTestnet": "true",
    "heat.deleteBlockchain": "true",
    "heat.deleteHeatDb": "true",
    "heat.isOffline": "true",
    "heat.isSilent": "false",
    "heat.numberOfForkConfirmations": "0",
    "heat.shareMyAddress": "false",
    "heat.disableGenerateBlocksThread": "true",
    "heat.disableGetMoreBlocksThread": "true",
    "heat.enableFakeForging": "true",
    "heat.savePeers": "false",
    "heat.disableProcessTransactionsThread": "true",
    "heat.disableRemoveUnconfirmedTransactionsThread": "true",
    "heat.disableRebroadcastTransactionsThread": "true",
    "heat.disablePeerUnBlacklistingThread": "true",
    "heat.getMorePeers": "false"
  }
};

var PATHS = {
  src: [
    'src/*.ts',
    'src/**/*.ts'
  ]
};

gulp.task('clean', function () {
  var del = require('del');
  return del(['dist']);
});

gulp.task('ts2js', function () {
  var typescript = require('gulp-typescript');
  var sourcemaps = require('gulp-sourcemaps');
  var tscConfig = require('./tsconfig.json');
  var extend = require('util')._extend;
  var concat = require('gulp-concat');

  return gulp.src(PATHS.src)
    .pipe(sourcemaps.init())
    .pipe(typescript(extend(tscConfig.compilerOptions)))
    .pipe(concat('index.js'))
    .pipe(sourcemaps.write('../dist'))
    .pipe(gulp.dest('dist'));
});

gulp.task('verify', function (cb) {
  var path = require('path');
  var fs = require('fs');
  if (!heatledger) {
    util.log(chalk.red.bold("ERROR")+" you did not create a heatledger.json file");
  }
  else if (!heatledger.dir) {
    util.log(chalk.red.bold("ERROR")+" missing 'dir' property in heatledger.json, make sure it points to HEAT server installation directory");
  }
  else if (!fs.existsSync(heatledger.dir)) {
    util.log(chalk.red.bold("ERROR")+" heatledger.json 'dir' path value points to non existing file");
  }
  else {
    var isWin = /^win/.test(process.platform);
    var heatbin = isWin ? path.join(heatledger.dir, 'bin', 'heatledger.bat') : path.join(heatledger.dir, 'bin', 'heatledger');
    if (!fs.existsSync(heatbin)) {
      util.log(chalk.red.bold("ERROR")+" could not find "+heatbin+" in installation directory");
    }
    else {
      util.log(chalk.green.bold("VERIFIED")+" you are good to go!");
    }
  }
});

/**
 * To test a microservice we write a javascript test script which is passed
 * to the heatledger binary as its -run paramater.
 * Upon seeing the -run parameter the heatledger server will after loading
 * execute this test script which in turns performs the test.
 *
 * Usage:
 *
 *    `gulp test --run "script.to.execute()" --mode fake`
 *
 * Parameters:
 *
 *    --heatdir     Absolute path to heat installation directory.
 *                  Note: The installation directory folder layout looks like this
 *
 *                    - heatledger            <-- This is the installation directory
 *                      - bin
 *                      - blockchain
 *                      - conf
 *                      - lib
 *                      etc...
 *
 *    --run         The script to execute, must be surrounded in quotes ("..")
 *
 *    --config      The path to a json document whose contents will be encoded to a single line string
 *                  and are passed to HEAT server as the --properties argument, each property in the
 *                  json object will be added to HEAT configuration properties.
 *
 *    --verbose     When provided will also include all console output from heat server,
 *                  otherwise only console output from your script is shown.
 *
 *    --mode        Either; main, test or fake (default)
 */
gulp.task('test', ['build'], function (cb) {
  var argv = require('yargs').argv;
  var exec = require('child_process').exec;
  var spawn = require('child_process').spawn;
  var path = require('path');
  var conf = modes[argv.mode||'fake'];
  var properties = getProperties(argv.config, conf);

  var scriptsDir = path.join(__dirname, 'dist');
  var isWin = /^win/.test(process.platform);
  var heatbin = isWin ? "bin\heatledger.bat" : "bin/heatledger";
  var heatdir = (heatledger&&heatledger.dir) || argv.heatdir;
  var sourcedir = path.join(__dirname, 'src');
  var args = ["-path", scriptsDir, "-run", argv.run, "-sourcedir", sourcedir, "-properties", properties];
  var server = spawn(heatbin, args, { cwd: heatdir });

  function logVerbose(msg) {
    if (!msg || msg.trim().length == 0) return;
    var lines = msg.split(/(\r?\n)/g);
    for (var i=0; i<lines.length; i++) {
      if (lines[i].match(/\S/)) {
        util.log(lines[i]);
      }
    }
  }

  function logScript(msg) {
    if (!msg || msg.trim().length == 0) return;
    var lines = msg.split(/(\r?\n)/g);
    for (var i=0; i<lines.length; i++) {
      if (lines[i].match(/\S/)) {
        // matches 2017-04-30 21:37:18 [main] INFO  com.heatledger.HeatProperties - heat.replicatorEnabled = "false"
        var parts = /\S+\s+\S+\s+\[.*\]\s+\S+\s+(\S+)/.exec(lines[i]);
        if (parts) {
          var className = parts[1];
          if (className.trim() == "<script>") {
            var cleaned = lines[i].replace(/(^.*<script>\s+-)/,chalk.red("<script>"));
            util.log(cleaned);
          }
        }
        // matches 21:32:33,278 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
        else if (lines[i].match(/^.*\|-\S+\s+in\s+ch.qos.logback/)) {
          continue;
        }
        else {
          util.log(lines[i]);
        }
      }
    }
  }

  var log = argv.verbose ? logVerbose : logScript;

  server.stdout.on('data', (data) => { log(data+"") });
  server.stderr.on('data', (data) => { log(data+"") });
});

function getProperties(configPath, conf) {
  var properties = null;
  try {
    properties = require(configPath)||{};
  } catch (e) {
    console.log("Either not provided or cant load --config path "+configPath);
  }
  var temp = {};
  _.extendOwn(temp, conf);
  _.extendOwn(temp, properties);
  properties = JSON.stringify(temp);
  return properties;
}

gulp.task('inject', ['build'], function (cb) {
  var del = require('del');
  var path = require('path');
  var distDir = path.join(__dirname, 'dist');
  var heatdir = "/home/dirk/git/heatledger";
  var scriptsDir = path.join(heatdir, 'scripts');
  del([scriptsDir+"/*"]);
  return gulp.src(['dist/*'])
    .pipe(gulp.dest(scriptsDir));
});

gulp.task('build', ['clean','ts2js']);
gulp.task('default', ['build']);
<|endoftext|>


<commit_before>/*
 * cahoots-api
 *
 * Copyright Cahoots.pw
 * MIT Licensed
 *
 */

/**
 * @author André König <andre.koenig@posteo.de>
 *
 */

'use strict';

var http = require('http');

var debug = require('debug')('cahoots:api:OrganizationsResource');

var services = require('cahoots-api-services');
var schemes = require('cahoots-api-schemes');
var validator = require('cahoots-api-validator');

var middlewares = require('./middlewares/');

module.exports = function instantiate () {
    var resource = new OrganizationsResource();

    return [
        {
            method: 'GET',
            path: '/organizations',
            handler: resource.list.bind(resource)
        },
        {
            method: 'GET',
            path: '/organizations/:id',
            handler: resource.one.bind(resource)
        },
        {
            method: 'POST',
            path: '/organizations',
            handler: resource.insert.bind(resource),
            middlewares: [middlewares.authentication()]
        }
    ];
};

/**
 * The /organizations resource.
 *
 */
function OrganizationsResource () {
    this.$service = services('organization');
    this.$schema = schemes('organization');
}

/**
 * POST /organizations
 *
 * Persists a new organization.
 *
 */
OrganizationsResource.prototype.insert = function insert (req, res) {
    var self = this;
    var organization = req.body;
    var schema = this.$schema.insert;

    function onValidation (err) {
        if (err) {
            debug('Validation failed. Insert of organization impossible: %j', err);
            return res.status(400).send(http.STATUS_CODES[400]);
        }

        self.$service.save(organization, onSave);
    }

    function onSave (err, organization) {
        if (err) {
            debug('Error while saving a new organization: %j', err);

            return res.status(500).send(http.STATUS_CODES[500]);
        }

        res.status(201).json(organization);
    }

    validator(schema).check(organization, onValidation);
};

/**
 * GET /organizations/:id
 *
 * Finds an organization by id.
 *
 */
OrganizationsResource.prototype.one = function one (req, res) {
    var id = req.params.id;

    function onFindById (err, organization) {
        if (err) {
            debug('Error while request the organization with the id "%s": %j', id, err);

            return res.status(500).send(http.STATUS_CODES[500]);
        }

        if (!organization) {
            return res.status(404).json({});
        }

        res.status(200).json(organization);
    }

    this.$service.findById(id, onFindById);
};

/**
 * GET /organizations[?ids=id0, id2]
 *
 * Lists all available organizations or organizations by an array of ids.
 *
 */
OrganizationsResource.prototype.list = function list (req, res) {
    var ids = req.query.ids;

    function onFind (err, organizations) {
        if (err) {
            debug('Error while requesting organizations: %j', err);

            return res.status(500).send(http.STATUS_CODES[500]);
        }

        if (!organizations.length) {
            return res.status(404).json(organizations);
        }

        res.status(200).json(organizations);
    }

    if (ids && ids.indexOf(',') !== -1) {
        ids = ids.split(',');

        return this.$service.findByIds(ids, onFind);
    }

    this.$service.findAll(onFind);
};
<commit_msg>More debug messages.<commit_after>/*
 * cahoots-api
 *
 * Copyright Cahoots.pw
 * MIT Licensed
 *
 */

/**
 * @author André König <andre.koenig@posteo.de>
 *
 */

'use strict';

var http = require('http');

var debug = require('debug')('cahoots:api:OrganizationsResource');

var services = require('cahoots-api-services');
var schemes = require('cahoots-api-schemes');
var validator = require('cahoots-api-validator');

var middlewares = require('./middlewares/');

module.exports = function instantiate () {
    var resource = new OrganizationsResource();

    return [
        {
            method: 'GET',
            path: '/organizations',
            handler: resource.list.bind(resource)
        },
        {
            method: 'GET',
            path: '/organizations/:id',
            handler: resource.one.bind(resource)
        },
        {
            method: 'POST',
            path: '/organizations',
            handler: resource.insert.bind(resource),
            middlewares: [middlewares.authentication()]
        }
    ];
};

/**
 * The /organizations resource.
 *
 */
function OrganizationsResource () {
    this.$service = services('organization');
    this.$schema = schemes('organization');
}

/**
 * POST /organizations
 *
 * Persists a new organization.
 *
 */
OrganizationsResource.prototype.insert = function insert (req, res) {
    var self = this;
    var organization = req.body;
    var schema = this.$schema.insert;

    function onValidation (err) {
        if (err) {
            debug('Validation failed. Insert of organization impossible: %j', err);
            return res.status(400).send(http.STATUS_CODES[400]);
        }

        self.$service.save(organization, onSave);
    }

    function onSave (err, organization) {
        if (err) {
            debug('Error while saving a new organization: %j', err);

            return res.status(500).send(http.STATUS_CODES[500]);
        }

        res.status(201).json(organization);
    }

    validator(schema).check(organization, onValidation);
};

/**
 * GET /organizations/:id
 *
 * Finds an organization by id.
 *
 */
OrganizationsResource.prototype.one = function one (req, res) {
    var id = req.params.id;

    function onFindById (err, organization) {
        if (err) {
            debug('Error while request the organization with the id "%s": %j', id, err);

            return res.status(500).send(http.STATUS_CODES[500]);
        }

        if (!organization) {
            return res.status(404).json({});
        }

        debug('Found one organization by id "%s": %j', id, organization);

        res.status(200).json(organization);
    }

    this.$service.findById(id, onFindById);
};

/**
 * GET /organizations[?ids=id0, id2]
 *
 * Lists all available organizations or organizations by an array of ids.
 *
 */
OrganizationsResource.prototype.list = function list (req, res) {
    var ids = req.query.ids;

    function onFind (err, organizations) {
        if (err) {
            debug('Error while requesting organizations: %j', err);

            return res.status(500).send(http.STATUS_CODES[500]);
        }

        if (!organizations.length) {
            return res.status(404).json(organizations);
        }

        debug('Found %d organization(s)', organizations.length);

        res.status(200).json(organizations);
    }

    if (ids && ids.indexOf(',') !== -1) {
        ids = ids.split(',');

        return this.$service.findByIds(ids, onFind);
    }

    this.$service.findAll(onFind);
};
<|endoftext|>


<commit_before>var nunjucks = require('nunjucks');

/**
 * @dgService templateEngine
 * @description A nunjucks powered template rendering engine
 */
module.exports = function templateEngine(templateFinder) {

  return {

    /**
     * Nunjucks specific options, such as using `{$ $}` for nunjucks interpolation
     * rather than `{{ }}`, which conflicts with AngularJS
     */
    config: {},

    filters: [],
    tags: [],

    getRenderer: function() {
      var loader = new nunjucks.FileSystemLoader(templateFinder.templateFolders, {watch: false, noCache: true});
      var engine = new nunjucks.Environment(loader, this.config);

      // Configure nunjucks with the custom filters
      this.filters.forEach(function(filter) {
        engine.addFilter(filter.name, filter.process);
      });

      // Configure nunjucks with the custom tags
      this.tags.forEach(function(tag) {
        engine.addExtension(tag.tags[0], tag);
      });

      return function render(template, data) {
        return engine.render(template, data);
      };
    }
  };
};
<commit_msg>fix(nunjucks): explicitly set autoescaping to off<commit_after>var nunjucks = require('nunjucks');

/**
 * @dgService templateEngine
 * @description A nunjucks powered template rendering engine
 */
module.exports = function templateEngine(templateFinder) {

  return {

    /**
     * Nunjucks specific options, such as using `{$ $}` for nunjucks interpolation
     * rather than `{{ }}`, which conflicts with AngularJS
     */
    config: {autoescape: false},

    filters: [],
    tags: [],

    getRenderer: function() {
      var loader = new nunjucks.FileSystemLoader(templateFinder.templateFolders, {watch: false, noCache: true});
      var engine = new nunjucks.Environment(loader, this.config);

      // Configure nunjucks with the custom filters
      this.filters.forEach(function(filter) {
        engine.addFilter(filter.name, filter.process);
      });

      // Configure nunjucks with the custom tags
      this.tags.forEach(function(tag) {
        engine.addExtension(tag.tags[0], tag);
      });

      return function render(template, data) {
        return engine.render(template, data);
      };
    }
  };
};
<|endoftext|>


<commit_before>var express = require('express');
var router = express.Router();
var async = require('async');
var bzVote = require('../biz/votelogic.js');
var bzVoter = require('../biz/voterlogic.js');
var mongoose = require('mongoose');

module.exports = function() {

	var bizVote = bzVote();
	var bizVoter = bzVoter();

	// candidate-list
	router.post('/list', function(req, res) {
		async.map(req.body,
			function (id, cb) {
				mongoose.models.candidate.findOne({ _id: id }, function (error, response) {
					if (error != null) {
						cb(error);
					} else {
						cb(null, response);
					}
				});
			},
			function (error, results) {
				if (error != null) {
					res.status(500).send(error);
				} else {
					if (results == null || results == undefined || results.length == 0) {
						res.status(404).send();
					} else {
						const cleanResults = [];
						results.forEach(function(result) {
							if (result) {
								cleanResults.push(result);
							}
						});
						if (results.length == 0) {
							res.status(404).send();
						} else {
							res.status(200).send(cleanResults);
						}
					}
				}
			});
	});

	// candidate - elections - votes
	router.get('/:candidateId/elections/:electionId/votes', function(req, res) {
		getVotes(req, res, null, { _id: req.params.candidateId, "candidateElections.electionId" : req.params.electionId }, req.params.electionId);
	});

	router.get('/:candidateId/elections/:electionId/votes/:id', function(req, res) {
		getVotes(req, res, null, { _id: req.params.candidateId,
			candidateElections: { $elemMatch: { electionId : req.params.electionId,
				votes: { $elemMatch: { _id: req.params.id }} }}}, req.params.electionId, req.params.id);
	});

	function getVotes(req, res, next, filter, electionId, voteId) {
		mongoose.models.candidate.findOne(filter, function(error, candidate) {
			if (error != null) {
				res.status(500).send(error);
			} else {
                if (candidate == null || candidate == undefined) {
                    res.status(404).send();
                } else {
                	var votes = [];
                	candidate.candidateElections.forEach(function(election) {
                		if (election.electionId == electionId) {
                			if (voteId == null || voteId == undefined) {
	                			votes = election.votes;
                			} else {
                				votes = [];
                				election.votes.forEach(function(vt) {
                					if(vt._id == voteId) {
                						votes.push(vt);
                					}
                				})
                			}
                		}
                	})
                    res.status(200).send(votes);
				}
			}
		});
	}

	router.post('/:candidateId/elections/:electionId/votes', function(req, res) {
		var vote = new mongoose.models.vote(req.body);
		bizVoter.voterCanVote(vote.voterId, function(error, result) {
			if (!result) {
				res.status(500).send('Voter cannot vote until previous vote expires');
			} else {

				mongoose.models.election.findOne( { _id: req.params.electionId }, function(error, election) {
					if (error) {
						res.status(500).send(error);
					} else {
						if (election == null || election == undefined) {
							res.status(500).send('Cannot find election for vote.');
						} else {
							bizVote.setEndtimeAndExpired(vote, election);
							mongoose.models.candidate.findOne( { _id: req.params.candidateId, "candidateElections.electionId" : req.params.electionId },
								function (error, response) {
								if (error != null) {
									res.status(500).send(error);
								} else {
									if (response == null || response == undefined || response.length == 0) {
										res.status(404).send();
									} else  {
										mongoose.models.candidate.update(
											{ _id: req.params.candidateId,
											  "candidateElections.electionId" : req.params.electionId },
											{
												$push: {
													"candidateElections.$.votes" : {
														$each: [ vote ]
													}
												}
											},
											{ runValidators: true },
											function (error) {
												if (error != null) {
													res.status(500).send(error)
												} else {
													mongoose.models.candidate.findOne( { _id: req.params.candidateId },
														function (error, response) {
															res.status(201).send(req.originalUrl + "/" + vote._id );
														});
												}
											}
										);
									}
								}
							});
						}
					}
				});
			}

		});
	});

	router.delete('/:candidateId/elections/:electionId/votes/:id', function(req, res) {
		mongoose.models.candidate.findOne( { _id: req.params.candidateId, "candidateElections.electionId" : req.params.electionId },
			function (error, response) {
			if (error != null) {
				res.status(500).send(error);
			} else {
				if (response == null || response == undefined || response.length == 0) {
					res.status(404).send();
				} else  {
					mongoose.models.candidate.update(
						{ _id: req.params.candidateId, "candidateElections.electionId" : req.params.electionId },
						{
							$pull: {
								"candidateElections.$.votes": { _id: req.params.id }
							}
						},
						{ runValidators: true },
						function (error) {
							if (error != null) {
								res.status(500).send(error)
							} else {
								res.status(200).send();
							}
						}
					);
				}
			}
		});
	});

	// candidate - elections
	router.get('/:candidateId/elections', function(req, res) {
		getElections(req, res, null, { _id: req.params.candidateId });
	});

	router.get('/:candidateId/elections/:id', function(req, res) {
		getElections(req, res, null, { _id: req.params.candidateId, "candidateElections.electionId" : req.params.id });
	});

	function getElections(req, res, next, filter) {
		mongoose.models.candidate.findOne(filter, function(error, candidate) {
			if (error != null) {
				res.status(500).send(error);
			} else {
                if (candidate == null || candidate == undefined) {
                    res.status(404).send();
                } else {
                    res.status(200).send(candidate.candidateElections);
				}
			}
		});
	}

	router.post('/:candidateId/elections', function(req, res) {
		var candidateElection = new mongoose.models.candidateElection({electionId: req.body.electionId, value: 0});
		mongoose.models.candidate.findOne( { _id: req.params.candidateId }, function (error, response) {
			if (error != null) {
				res.status(500).send(error);
			} else {
				if (response == null || response == undefined || response.length == 0) {
					res.status(404).send();
				} else  {
					mongoose.models.candidate.update(
						{ _id: req.params.candidateId },
						{
							$push: {
								candidateElections : {
									$each: [ candidateElection ]
								}
							}
						},
						{ runValidators: true },
						function (error) {
							if (error != null) {
								res.status(500).send(error)
							} else {
								mongoose.models.candidate.findOne( { _id: req.params.candidateId },
									function (error, candidate) {
										res.status(201).send(req.originalUrl + "/" + req.body.electionId );
									});
							}
						}
					);
				}
			}
		});

	});

	router.delete('/:candidateId/elections/:id', function(req, res) {
		mongoose.models.candidate.findOne( { _id: req.params.candidateId }, function (error, response) {
			if (error != null) {
				res.status(500).send(error);
			} else {
				if (response == null || response == undefined || response.length == 0) {
					res.status(404).send();
				} else  {
					mongoose.models.candidate.update(
						{ _id: response._id },
						{
							$pull: {
								'candidateElections': { electionId: req.params.id }
							}
						},
						{ runValidators: true },
						function (error) {
							if (error != null) {
								res.status(500).send(error)
							} else {
								res.status(200).send();
							}
						}
					);
				}
			}
		});
	});

	// candidate
	router.get('/', function(req, res) {
		mongoose.models.candidate.find(null, returnGet(req, res))
	});

	router.get('/:id', function(req, res) {
		mongoose.models.candidate.findOne({ _id: req.params.id }, returnGet(req, res));
	});

	function returnGet (req, res) {
		return function (error, response) {
			if (error != null) {
				res.status(500).send(error);
			} else {
				if (response == null || response == undefined || response.length == 0) {
					res.status(404).send();
				} else {
					res.status(200).send(response)
				}
			}
		}
	}

	router.post('/', function(req, res) {
		var candidate = new mongoose.models.candidate(req.body);
		candidate.save(function (error, response) {
			if (error != null) {
				res.status(500).send(error);
			} else {
				var responseUrl = req.originalUrl + "/" + response._id;

				if (req.body.electionId && req.body.electionId.length > 0) {
					mongoose.models.election.findByIdAndUpdate(mongoose.Types.ObjectId(req.body.electionId),
					    {$push: {"candidateIds": response._id}},
					    {safe: true, upsert: true},
					    function(error, model) {
					    	if (error) {
								res.status(500).send(error);
						    } else {
								res.status(201).send(responseUrl);
						    }
					    });
				} else {
					res.status(201).send(responseUrl);
				}
			}
		});
	});

	router.put('/:id', function(req, res) {
		mongoose.models.candidate.findOne({ _id: req.params.id}, function(error, response) {
			if (error != null) {
				res.status(500).send(error);
			} else {
				if (response == null || response == undefined || response.length == 0) {
					var candidate = new mongoose.models.candidate(req.body);
					candidate.save(function (error, response) {
						if (error != null) {
							res.status(500).send(error);
						} else {
							res.status(201).send(req.originalUrl + "/" + response._id);
						}
					});
				} else {
					mongoose.models.candidate.update( { _id: response._id } ,
						req.body,
						{ runValidators: true },
						function (error) {
						if (error != null) {
							res.status(500).send(error);
						} else {
							res.status(200).send(req.originalUrl);
						}
					});
				}
			}
		});
	});

	router.delete('/:id', function(req, res) {
		mongoose.models.candidate.find({_id: req.params.id}, function (error, response) {
			if (error != null) {
				res.status(500).send(error)
			} else {
				if (response == null || response == undefined || response.length == 0) {
					res.status(404).send();
				} else {
					mongoose.models.candidate.remove({_id: req.params.id }, function(error) {
						if (error != null) {
							res.status(500).send(error);
						} else {
							mongoose.models.election.update({candidateIds: req.params.id},
								{ $pullAll: {candidateIds: [req.params.id] }}, function(error) {
									if (error != null) {
										res.status(500).send(error);
									} else {
										res.status(200).send();
									}
								});
						}
					});
				}
			}
		})
	});

	return router;
}
<commit_msg>linting<commit_after>const express = require('express');
const router = express.Router();
const async = require('async');
const bzVote = require('../biz/votelogic.js');
const bzVoter = require('../biz/voterlogic.js');
const mongoose = require('mongoose');

module.exports = function () {
  const bizVote = bzVote();
  const bizVoter = bzVoter();

  // candidate-list
  router.post('/list', (req, res) => {
    async.map(req.body,
      (id, cb) => {
        mongoose.models.candidate.findOne({_id: id}, (error, response) => {
          if (error === null) {
            cb(null, response);
          } else {
            cb(error);
          }
        });
      },
      (error, results) => {
        if (error === null) {
          if (results === null || results === undefined || results.length === 0) {
            res.status(404).send();
          } else {
            const cleanResults = [];
            results.forEach(result => {
              if (result) {
                cleanResults.push(result);
              }
            });
            if (results.length === 0) {
              res.status(404).send();
            } else {
              res.status(200).send(cleanResults);
            }
          }
        } else {
          res.status(500).send(error);
        }
      });
  });

  // candidate - elections - votes
  router.get('/:candidateId/elections/:electionId/votes', (req, res) => {
    getVotes(req, res, null, {_id: req.params.candidateId, 'candidateElections.electionId': req.params.electionId}, req.params.electionId);
  });

  router.get('/:candidateId/elections/:electionId/votes/:id', (req, res) => {
    getVotes(req, res, null, {_id: req.params.candidateId,
      candidateElections: {$elemMatch: {electionId: req.params.electionId,
        votes: {$elemMatch: {_id: req.params.id}}}}}, req.params.electionId, req.params.id);
  });

  function getVotes(req, res, next, filter, electionId, voteId) {
    mongoose.models.candidate.findOne(filter, (error, candidate) => {
      if (error === null) {
        if (candidate === null || candidate === undefined) {
          res.status(404).send();
        } else {
          let votes = [];
          candidate.candidateElections.forEach(election => {
            if (election.electionId === electionId) {
              if (voteId === null || voteId === undefined) {
                votes = election.votes;
              } else {
                votes = [];
                election.votes.forEach(vt => {
                  if (vt._id === voteId) {
                    votes.push(vt);
                  }
                });
              }
            }
          });
          res.status(200).send(votes);
        }
      } else {
        res.status(500).send(error);
      }
    });
  }

  router.post('/:candidateId/elections/:electionId/votes', (req, res) => {
    const vote = new mongoose.models.vote(req.body);
    bizVoter.voterCanVote(vote.voterId, (error, result) => {
      if (result) {
        mongoose.models.election.findOne({_id: req.params.electionId}, (error, election) => {
          if (error) {
            res.status(500).send(error);
          } else {
            if (election === null || election === undefined) {
              res.status(500).send('Cannot find election for vote.');
            } else {
              bizVote.setEndtimeAndExpired(vote, election);
              mongoose.models.candidate.findOne({_id: req.params.candidateId, 'candidateElections.electionId': req.params.electionId},
                (error, response) => {
                  if (error === null) {
                    if (response === null || response === undefined || response.length === 0) {
                      res.status(404).send();
                    } else {
                      mongoose.models.candidate.update(
                        {_id: req.params.candidateId,
                          'candidateElections.electionId': req.params.electionId},
                        {
                          $push: {
                            'candidateElections.$.votes': {
                              $each: [vote]
                            }
                          }
                        },
                        {runValidators: true},
                        error => {
                          if (error === null) {
                            mongoose.models.candidate.findOne({_id: req.params.candidateId},
                              () => {
                                res.status(201).send(req.originalUrl + '/' + vote._id);
                              });
                          } else {
                            res.status(500).send(error);
                          }
                        }
                      );
                    }
                  } else {
                    res.status(500).send(error);
                  }
                });
            }
          }
        });
      } else {
        res.status(500).send('Voter cannot vote until previous vote expires');
      }
    });
  });

  router.delete('/:candidateId/elections/:electionId/votes/:id', (req, res) => {
    mongoose.models.candidate.findOne({_id: req.params.candidateId, 'candidateElections.electionId': req.params.electionId},
      (error, response) => {
        if (error === null) {
          if (response === null || response === undefined || response.length === 0) {
            res.status(404).send();
          } else {
            mongoose.models.candidate.update(
              {_id: req.params.candidateId, 'candidateElections.electionId': req.params.electionId},
              {
                $pull: {
                  'candidateElections.$.votes': {_id: req.params.id}
                }
              },
              {runValidators: true},
              error => {
                if (error === null) {
                  res.status(200).send();
                } else {
                  res.status(500).send(error);
                }
              });
          }
        } else {
          res.status(500).send(error);
        }
      });
  });

  // candidate - elections
  router.get('/:candidateId/elections', (req, res) => {
    getElections(req, res, null, {_id: req.params.candidateId});
  });

  router.get('/:candidateId/elections/:id', (req, res) => {
    getElections(req, res, null, {_id: req.params.candidateId, 'candidateElections.electionId': req.params.id});
  });

  function getElections(req, res, next, filter) {
    mongoose.models.candidate.findOne(filter, (error, candidate) => {
      if (error === null) {
        if (candidate === null || candidate === undefined) {
          res.status(404).send();
        } else {
          res.status(200).send(candidate.candidateElections);
        }
      } else {
        res.status(500).send(error);
      }
    });
  }

  router.post('/:candidateId/elections', (req, res) => {
    const candidateElection = new mongoose.models.candidateElection({electionId: req.body.electionId, value: 0});
    mongoose.models.candidate.findOne({_id: req.params.candidateId}, (error, response) => {
      if (error === null) {
        if (response === null || response === undefined || response.length === 0) {
          res.status(404).send();
        } else {
          mongoose.models.candidate.update(
            {_id: req.params.candidateId},
            {
              $push: {
                candidateElections: {
                  $each: [candidateElection]
                }
              }
            },
            {runValidators: true},
            error => {
              if (error === null) {
                mongoose.models.candidate.findOne({_id: req.params.candidateI},
                  () => {
                    res.status(201).send(req.originalUrl + '/' + req.body.electionId);
                  });
              } else {
                res.status(500).send(error);
              }
            }
          );
        }
      } else {
        res.status(500).send(error);
      }
    });
  });

  router.delete('/:candidateId/elections/:id', (req, res) => {
    mongoose.models.candidate.findOne({_id: req.params.candidateId}, (error, response) => {
      if (error === null) {
        if (response === null || response === undefined || response.length === 0) {
          res.status(404).send();
        } else {
          mongoose.models.candidate.update(
            {_id: response._id},
            {
              $pull: {
                candidateElections: {electionId: req.params.id}
              }
            },
            {runValidators: true},
            error => {
              if (error === null) {
                res.status(200).send();
              } else {
                res.status(500).send(error);
              }
            }
          );
        }
      } else {
        res.status(500).send(error);
      }
    });
  });

  // candidate
  router.get('/', (req, res) => {
    mongoose.models.candidate.find(null, returnGet(req, res));
  });

  router.get('/:id', (req, res) => {
    mongoose.models.candidate.findOne({_id: req.params.id}, returnGet(req, res));
  });

  function returnGet(req, res) {
    return (error, response) => {
      if (error === null) {
        if (response === null || response === undefined || response.length === 0) {
          res.status(404).send();
        } else {
          res.status(200).send(response);
        }
      } else {
        res.status(500).send(error);
      }
    };
  }

  router.post('/', (req, res) => {
    const candidate = new mongoose.models.candidate(req.body);
    candidate.save((error, response) => {
      if (error === null) {
        const responseUrl = req.originalUrl + '/' + response._id;

        if (req.body.electionId && req.body.electionId.length > 0) {
          mongoose.models.election.findByIdAndUpdate(mongoose.Types.ObjectId(req.body.electionId),
              {$push: {candidateIds: response._id}},
              {safe: true, upsert: true},
              error => {
                if (error) {
                  res.status(500).send(error);
                } else {
                  res.status(201).send(responseUrl);
                }
              });
        } else {
          res.status(201).send(responseUrl);
        }
      } else {
        res.status(500).send(error);
      }
    });
  });

  router.put('/:id', (req, res) => {
    mongoose.models.candidate.findOne({_id: req.params.id}, (error, response) => {
      if (error === null) {
        if (response === null || response === undefined || response.length === 0) {
          const candidate = new mongoose.models.candidate(req.body);
          candidate.save((error, response) => {
            if (error === null) {
              res.status(201).send(req.originalUrl + '/' + response._id);
            } else {
              res.status(500).send(error);
            }
          });
        } else {
          mongoose.models.candidate.update({_id: response._id},
            req.body,
            {runValidators: true},
            error => {
              if (error === null) {
                res.status(200).send(req.originalUrl);
              } else {
                res.status(500).send(error);
              }
            });
        }
      } else {
        res.status(500).send(error);
      }
    });
  });

  router.delete('/:id', (req, res) => {
    mongoose.models.candidate.find({_id: req.params.id}, (error, response) => {
      if (error === null) {
        if (response === null || response === undefined || response.length === 0) {
          res.status(404).send();
        } else {
          mongoose.models.candidate.remove({_id: req.params.id}, error => {
            if (error === null) {
              mongoose.models.election.update({candidateIds: req.params.id},
                {$pullAll: {candidateIds: [req.params.id]}}, error => {
                  if (error === null) {
                    res.status(200).send();
                  } else {
                    res.status(500).send(error);
                  }
                });
            } else {
              res.status(500).send(error);
            }
          });
        }
      } else {
        res.status(500).send(error);
      }
    });
  });

  return router;
};
<|endoftext|>


<commit_before>// http://blog.ponyfoo.com/2014/01/27/my-first-gulp-adventure
var gulp = require('gulp');
var gutil = require('gulp-util');
var bump = require('gulp-bump');
var git = require('gulp-git');
var jshint = require('gulp-jshint');
var clean = require('gulp-clean');
var rename = require('gulp-rename');
var uglify = require('gulp-uglify');
var size = require('gulp-size');
var prompt = require('gulp-prompt');

var BUMP_TYPES = ['major', 'minor', 'patch', 'prerelease'];

gulp.task('lint', function () {
  return gulp.src('./src/*.js')
    .pipe(jshint())
    .pipe(jshint.reporter('default'));
});

gulp.task('clean', function () {
  return gulp.src('./dist', { read: false })
    .pipe(clean());
});

gulp.task('build', ['clean'], function () {
  return gulp.src('./src/jquery.textarea_auto_expand.js')
    .pipe(gulp.dest('./dist'))
    .pipe(rename('jquery.textarea_auto_expand.min.js'))
    .pipe(uglify())
    .pipe(size({showFiles: true}))
    .pipe(gulp.dest('./dist'));
});

gulp.task('watch', function() {
  gulp.watch('src/*.js', ['lint', 'build']);
});

gulp.task('validation', function () {
  if (BUMP_TYPES.indexOf(gutil.env.bump) == -1)
    throw new Error('\nbump argument is required for gulp release\nSupported values: major, minor, patch, prerelease\n\nExample:\n\tgulp release --bump major');
});

gulp.task('bump', ['validation', 'build'], function () {
  return gulp.src(['./package.json'])
    .pipe(bump({type: gutil.env.bump}))
    .pipe(gulp.dest('./'));
});

gulp.task('tag', ['bump'], function () {
  var pkg = require('./package.json');
  var v = 'v' + pkg.version;
  var message = 'Release ' + v;

  return gulp.src('./')
    .pipe(git.commit(message))
    .pipe(git.tag(v, message))
    .pipe(git.push('origin', 'master', '--tags'))
    .pipe(gulp.dest('./'));
});

gulp.task('npm', ['tag'], function (done) {
  require('child_process').spawn('npm', ['publish'], { stdio: 'inherit' })
    .on('close', done);
});

gulp.task('test', ['lint', 'mocha']);
gulp.task('ci', ['build']);
//gulp.task('release', ['validation', 'npm']);
gulp.task('release', ['validation', 'bump']);<commit_msg>Add default task that just runs watch task.<commit_after>// http://blog.ponyfoo.com/2014/01/27/my-first-gulp-adventure
var gulp = require('gulp');
var gutil = require('gulp-util');
var bump = require('gulp-bump');
var git = require('gulp-git');
var jshint = require('gulp-jshint');
var clean = require('gulp-clean');
var rename = require('gulp-rename');
var uglify = require('gulp-uglify');
var size = require('gulp-size');
var prompt = require('gulp-prompt');

var BUMP_TYPES = ['major', 'minor', 'patch', 'prerelease'];

gulp.task('lint', function () {
  return gulp.src('./src/*.js')
    .pipe(jshint())
    .pipe(jshint.reporter('default'));
});

gulp.task('clean', function () {
  return gulp.src('./dist', { read: false })
    .pipe(clean());
});

gulp.task('build', ['clean'], function () {
  return gulp.src('./src/jquery.textarea_auto_expand.js')
    .pipe(gulp.dest('./dist'))
    .pipe(rename('jquery.textarea_auto_expand.min.js'))
    .pipe(uglify())
    .pipe(size({showFiles: true}))
    .pipe(gulp.dest('./dist'));
});

gulp.task('watch', function() {
  gulp.watch('src/*.js', ['lint', 'build']);
});

gulp.task('validation', function () {
  if (BUMP_TYPES.indexOf(gutil.env.bump) == -1)
    throw new Error('\nbump argument is required for gulp release\nSupported values: major, minor, patch, prerelease\n\nExample:\n\tgulp release --bump major');
});

gulp.task('bump', ['validation', 'build'], function () {
  return gulp.src(['./package.json'])
    .pipe(bump({type: gutil.env.bump}))
    .pipe(gulp.dest('./'));
});

gulp.task('tag', ['bump'], function () {
  var pkg = require('./package.json');
  var v = 'v' + pkg.version;
  var message = 'Release ' + v;

  return gulp.src('./')
    .pipe(git.commit(message))
    .pipe(git.tag(v, message))
    .pipe(git.push('origin', 'master', '--tags'))
    .pipe(gulp.dest('./'));
});

gulp.task('npm', ['tag'], function (done) {
  require('child_process').spawn('npm', ['publish'], { stdio: 'inherit' })
    .on('close', done);
});

gulp.task('test', ['lint', 'mocha']);
gulp.task('ci', ['build']);
//gulp.task('release', ['validation', 'npm']);
gulp.task('release', ['validation', 'bump']);

gulp.task('default', ['watch']);<|endoftext|>


<commit_before>import {splitStringValue} from "./utils";

const SPECIAL_ATTRIBUTE_SETTERS = /^(html|text|css)$/;
const customDataStorage = new window.WeakMap();

/**
 * Sets all attributes on the given element
 *
 * @param {Element} element
 * @param {mojave.types.OptionalKeyMap} attributes
 */
export function setAttrs (element, attributes)
{
    for (const key in attributes)
    {
        if (!attributes.hasOwnProperty(key))
        {
            continue;
        }

        const value = attributes[key];

        if (SPECIAL_ATTRIBUTE_SETTERS.test(key))
        {
            return;
        }

        if (value === null || value === false)
        {
            element.removeAttribute(key);
        }
        else
        {
            element.setAttribute(
                key,
                (value === true) ? key : ("" + value)
            );
        }
    }
}

/**
 * Returns the attribute value for the given html node
 *
 * @param {Element} element
 * @param {string} attribute
 * @returns {string | null}
 */
export function getAttr (element, attribute)
{
    return element.getAttribute(attribute);
}

/**
 * Updates the classes on the given element
 *
 * @private
 * @param {Element | Element[]} element
 * @param {string | string[]} classes
 * @param {string} method
 */
function updateClasses (element, classes, method)
{
    /** @type {Element[]} list */
    const list = Array.isArray(element) ? element : [element];
    const classList = splitStringValue(classes);

    for (let i = 0; i < list.length; i++)
    {
        for (let j = 0; j < classList.length; j++)
        {
            list[i].classList[method](classList[j]);
        }
    }
}

/**
 * Adds all given classes to the element
 *
 * @param {Element | Element[]} element
 * @param {string | string[]} classes
 */
export function addClass (element, classes)
{
    updateClasses(element, classes, "add");
}

/**
 * Remove all given classes from the element
 *
 * @param {Element | Element[]} element
 * @param {string | string[]} classes
 */
export function removeClass (element, classes)
{
    updateClasses(element, classes, "remove");
}

/**
 * Normalizes the key for *Data functions
 *
 * @private
 * @param {string} key
 * @returns {string}
 */
function normalizeDataKey (key)
{
    return key.replace(
        /-([a-z])/g,
        (matches) => matches[1].toUpperCase()
    );
}

/**
 * Sets the data on the given element
 *
 * @param {Element} element
 * @param {string} key
 * @param {*} value
 */
export function setData (element, key, value)
{
    key = normalizeDataKey(key);
    let storage = customDataStorage.get(element);

    if (storage === undefined)
    {
        storage = {};
        customDataStorage.set(element, storage);
    }

    storage[key] = value;
}

/**
 * Loads the data from the element
 *
 * @param {HTMLElement} element
 * @param {string} key
 * @returns {*}
 */
export function getData (element, key)
{
    const normalizedKey = normalizeDataKey(key);
    const storage = customDataStorage.get(element);

    if (typeof storage === "object" && storage[normalizedKey] !== undefined)
    {
        return storage[normalizedKey];
    }

    // @legacy IE <= 10 doesn't support dataset
    if (element.dataset === undefined)
    {
        return getAttr(element, `data-${key}`);
    }

    const value = element.dataset[normalizedKey];
    return value === undefined
        ? null
        : value;
}

/**
 * Determines whether the given attribute is set on the element
 *
 * @param {Element} element
 * @param {string} key
 * @returns {boolean}
 */
export function hasData (element, key)
{
    const normalizedKey = normalizeDataKey(key);
    const storage = customDataStorage.get(element);

    if (typeof storage === "object")
    {
        return storage[normalizedKey] !== undefined;
    }

    // @legacy IE <= 10 doesn't support dataset
    if (element.dataset === undefined)
    {
        return hasAttr(element, `data-${key}`);
    }

    return undefined !== element.dataset[normalizedKey];
}

/**
 * Returns all data in custom storage
 *
 * @param {HTMLElement} element
 * @returns {Object}
 */
export function getAllCustomData (element)
{
    return customDataStorage.get(element) || {};
}
<commit_msg>Refactor hasData to use its corresponding getter<commit_after>import {splitStringValue} from "./utils";

const SPECIAL_ATTRIBUTE_SETTERS = /^(html|text|css)$/;
const customDataStorage = new window.WeakMap();

/**
 * Sets all attributes on the given element
 *
 * @param {Element} element
 * @param {mojave.types.OptionalKeyMap} attributes
 */
export function setAttrs (element, attributes)
{
    for (const key in attributes)
    {
        if (!attributes.hasOwnProperty(key))
        {
            continue;
        }

        const value = attributes[key];

        if (SPECIAL_ATTRIBUTE_SETTERS.test(key))
        {
            return;
        }

        if (value === null || value === false)
        {
            element.removeAttribute(key);
        }
        else
        {
            element.setAttribute(
                key,
                (value === true) ? key : ("" + value)
            );
        }
    }
}

/**
 * Returns the attribute value for the given html node
 *
 * @param {Element} element
 * @param {string} attribute
 * @returns {string | null}
 */
export function getAttr (element, attribute)
{
    return element.getAttribute(attribute);
}

/**
 * Updates the classes on the given element
 *
 * @private
 * @param {Element | Element[]} element
 * @param {string | string[]} classes
 * @param {string} method
 */
function updateClasses (element, classes, method)
{
    /** @type {Element[]} list */
    const list = Array.isArray(element) ? element : [element];
    const classList = splitStringValue(classes);

    for (let i = 0; i < list.length; i++)
    {
        for (let j = 0; j < classList.length; j++)
        {
            list[i].classList[method](classList[j]);
        }
    }
}

/**
 * Adds all given classes to the element
 *
 * @param {Element | Element[]} element
 * @param {string | string[]} classes
 */
export function addClass (element, classes)
{
    updateClasses(element, classes, "add");
}

/**
 * Remove all given classes from the element
 *
 * @param {Element | Element[]} element
 * @param {string | string[]} classes
 */
export function removeClass (element, classes)
{
    updateClasses(element, classes, "remove");
}

/**
 * Normalizes the key for *Data functions
 *
 * @private
 * @param {string} key
 * @returns {string}
 */
function normalizeDataKey (key)
{
    return key.replace(
        /-([a-z])/g,
        (matches) => matches[1].toUpperCase()
    );
}

/**
 * Sets the data on the given element
 *
 * @param {Element} element
 * @param {string} key
 * @param {*} value
 */
export function setData (element, key, value)
{
    key = normalizeDataKey(key);
    let storage = customDataStorage.get(element);

    if (storage === undefined)
    {
        storage = {};
        customDataStorage.set(element, storage);
    }

    storage[key] = value;
}

/**
 * Loads the data from the element
 *
 * @param {HTMLElement} element
 * @param {string} key
 * @returns {*}
 */
export function getData (element, key)
{
    const normalizedKey = normalizeDataKey(key);
    const storage = customDataStorage.get(element);

    if (typeof storage === "object" && storage[normalizedKey] !== undefined)
    {
        return storage[normalizedKey];
    }

    // @legacy IE <= 10 doesn't support dataset
    if (element.dataset === undefined)
    {
        return getAttr(element, `data-${key}`);
    }

    const value = element.dataset[normalizedKey];
    return value === undefined
        ? null
        : value;
}

/**
 * Determines whether the given data attribute is set on the element
 *
 * @param {HTMLElement} element
 * @param {string} key
 * @returns {boolean}
 */
export function hasData (element, key)
{
    const value = getData(element, key);

    // Empty data attributes' value is an empty string
    if ("" === value)
    {
        return true;
    }

    return null !== (value || null);
}

/**
 * Returns all data in custom storage
 *
 * @param {HTMLElement} element
 * @returns {Object}
 */
export function getAllCustomData (element)
{
    return customDataStorage.get(element) || {};
}
<|endoftext|>


<commit_before>window.cls || (window.cls = {});

cls.DOMSearchView = function(id, name, container_class)
{

  this.createView = function(container)
  {
    container.clearAndRender(this._tmpl());
    this._search_container = container.childNodes[1];
    this._search.set_container(this._search_container);
    var query = '[handler="' + this.controls[SEARCHFIELD].handler + '"]';
    this._input = container.querySelector(query);
    this._search.set_form_input(this._input);
    this._search.set_info_element(container.getElementsByTagName('info')[0]);
    this._search.show_last_search();
  };

  const
  MOVE_HIGHLIGHT_UP = 0,
  MOVE_HIGHLIGHT_DOWN = 1,
  SEARCHFIELD = 2;

  this._tmpl = function()
  {
    return (
    [
      ['div',
        window.templates.dom_search_bar_content(this),
        'class', 'dom-search-controls'],
      ['div',
        ['div', 'class', 'dom-search mono'],
        'class', 'dom-search-container',
        'handler', 'clear-style-highlight-node'],
      ['div',
        ['info', '\u00A0'],
        'class', 'dom-search-info'],
    ]);
  };

  ActionHandlerInterface.apply(this);

  this.focus = function(event, container)
  {
    setTimeout(this._focus_input, 50);
  };

  this._focus_input = function()
  {
    if (this._input)
    {
      this._input.selectionStart = 0;
      this._input.selectionEnd = this._input.value.length;
      this._input.focus();
    }
  }.bind(this);

  this._onshortcut = function(action_id, event, target)
  {
    switch (action_id)
    {
      case 'highlight-next-match':
      {
        this._search.highlight_next();
        return false;
      }
      case 'highlight-previous-match':
      {
        this._search.highlight_previous();
        return false;
      }
      case "show-script":
      {
        this._search.inspect_selected_node();
        break;
      }

    }
  };

  this._onsearchfieldinput = function(event)
  {
    this._search.search_delayed();
  };

  this._init = function(id, name, container_class)
  {
    this.init(id, name, container_class);
    this._search = new DOMSearch();
    this.controls =
    [
      {
        handler: this.id + '-move-highlight-up',
        type: "search_control",
        class: "search-move-highlight-up",
        title: ui_strings.S_LABEL_MOVE_HIGHLIGHT_UP
      },
      {
        handler: this.id + '-move-highlight-down',
        type: "search_control",
        class: "search-move-highlight-down",
        title: ui_strings.S_LABEL_MOVE_HIGHLIGHT_DOWN
      },
      {
        handler: this.id + '-simple-text-search',
        shortcuts: this.id + '-simple-text-search',
        title: ui_strings.S_INPUT_DEFAULT_TEXT_SEARCH
      },
    ];
    [
      'search_type',
      'ignore_case',
      'search_only_selected_node',
    ].forEach(function(prop)
    {
      this.__defineGetter__(prop, function()
      {
        return this._search[prop];
      });
      this.__defineSetter__(prop, function(){});
    }, this);
    eventHandlers.input[this.controls[SEARCHFIELD].handler] =
      this._onsearchfieldinput.bind(this)
    eventHandlers.click[this.controls[MOVE_HIGHLIGHT_DOWN].handler] =
      this._onshortcut.bind(this, 'highlight-next-match');
    eventHandlers.click[this.controls[MOVE_HIGHLIGHT_UP].handler] =
      this._onshortcut.bind(this, 'highlight-previous-match');
    eventHandlers.mouseover['clear-style-highlight-node'] =
      this._search.clear_style_highlight_node.bind(this._search);
    var action_broker = ActionBroker.get_instance();
    action_broker.register_handler(this);
    action_broker.get_global_handler()
    .register_shortcut_listener(this.controls[SEARCHFIELD].shortcuts,
                                this._onshortcut.bind(this),
                                ['highlight-next-match',
                                 'highlight-previous-match',
                                 'hide-search']);
  };

  this._init(id, name, container_class);

};
<commit_msg>Also fixed the layout in the DOM search panel.<commit_after>window.cls || (window.cls = {});

cls.DOMSearchView = function(id, name, container_class)
{

  this.createView = function(container)
  {
    container.clearAndRender(this._tmpl());
    this._search_container = container.childNodes[1];
    this._search.set_container(this._search_container);
    var query = '[handler="' + this.controls[SEARCHFIELD].handler + '"]';
    this._input = container.querySelector(query);
    this._search.set_form_input(this._input);
    this._search.set_info_element(container.getElementsByTagName('info')[0]);
    this._search.show_last_search();
  };

  const
  MOVE_HIGHLIGHT_UP = 0,
  MOVE_HIGHLIGHT_DOWN = 1,
  SEARCHFIELD = 2;

  this._tmpl = function()
  {
    return (
    [
      ['div',
        window.templates.dom_search_bar_content(this),
        'class', 'dom-search-controls'],
      ['div',
        ['div', 'class', 'dom-search mono'],
        'class', 'dom-search-container',
        'handler', 'clear-style-highlight-node'],
      ['div',
        ['info', '\u00A0'],
        'class', 'dom-search-info'],
    ]);
  };

  ActionHandlerInterface.apply(this);

  this.focus = function(event, container)
  {
    setTimeout(this._focus_input, 50);
  };

  this._focus_input = function()
  {
    if (this._input)
    {
      this._input.selectionStart = 0;
      this._input.selectionEnd = this._input.value.length;
      this._input.focus();
    }
  }.bind(this);

  this._onshortcut = function(action_id, event, target)
  {
    switch (action_id)
    {
      case 'highlight-next-match':
      {
        this._search.highlight_next();
        return false;
      }
      case 'highlight-previous-match':
      {
        this._search.highlight_previous();
        return false;
      }
      case "show-script":
      {
        this._search.inspect_selected_node();
        break;
      }

    }
  };

  this._onsearchfieldinput = function(event)
  {
    this._search.search_delayed();
  };

  this._init = function(id, name, container_class)
  {
    this.init(id, name, container_class);
    this._search = new DOMSearch();
    this.controls =
    [
      {
        handler: this.id + '-simple-text-search',
        shortcuts: this.id + '-simple-text-search',
        title: ui_strings.S_INPUT_DEFAULT_TEXT_SEARCH
      },
      {
        handler: this.id + '-move-highlight-up',
        type: "search_control",
        class: "search-move-highlight-up",
        title: ui_strings.S_LABEL_MOVE_HIGHLIGHT_UP
      },
      {
        handler: this.id + '-move-highlight-down',
        type: "search_control",
        class: "search-move-highlight-down",
        title: ui_strings.S_LABEL_MOVE_HIGHLIGHT_DOWN
      },

    ];
    [
      'search_type',
      'ignore_case',
      'search_only_selected_node',
    ].forEach(function(prop)
    {
      this.__defineGetter__(prop, function()
      {
        return this._search[prop];
      });
      this.__defineSetter__(prop, function(){});
    }, this);
    eventHandlers.input[this.controls[SEARCHFIELD].handler] =
      this._onsearchfieldinput.bind(this)
    eventHandlers.click[this.controls[MOVE_HIGHLIGHT_DOWN].handler] =
      this._onshortcut.bind(this, 'highlight-next-match');
    eventHandlers.click[this.controls[MOVE_HIGHLIGHT_UP].handler] =
      this._onshortcut.bind(this, 'highlight-previous-match');
    eventHandlers.mouseover['clear-style-highlight-node'] =
      this._search.clear_style_highlight_node.bind(this._search);
    var action_broker = ActionBroker.get_instance();
    action_broker.register_handler(this);
    action_broker.get_global_handler()
    .register_shortcut_listener(this.controls[SEARCHFIELD].shortcuts,
                                this._onshortcut.bind(this),
                                ['highlight-next-match',
                                 'highlight-previous-match',
                                 'hide-search']);
  };

  this._init(id, name, container_class);

};
<|endoftext|>


<commit_before>'use strict';

/* App module
 * ========================================= */

var ngMeme = angular.module('ngMeme', [])

ngMeme.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider){
    $routeProvider.when('/', {
      templateUrl: 'partials/root.html',
      controller: rootController
    });
    $routeProvider.when('/img:params', {
      templateUrl: 'partials/image.html',
      controller: imageController
    });
    $routeProvider.otherwise({
      redirectTo: '/'
    });
  }]);

/* End App module */

/* Controllers
 * ========================================= */

function mainController($scope, $route, $routeParams, $location, Toma){
  $scope.$route = $route;
  $scope.$location = $location;
  $scope.$routeParams = $routeParams;
  $scope.docRoot = window.location.origin + '/meme/#/';

  $scope.memeAreaHeight = function(chromeHeight){
    var windowHeight = window.innerHeight;
    var areaHeight = (windowHeight - chromeHeight) + 'px';
    return {'height' : areaHeight};
  }

  $scope.utf8ToBase64 = function(str){
    return window.btoa(unescape(encodeURIComponent(str))).replace(/=+$/, '');
  }
  $scope.b64ToUtf8 = function(str){
    return decodeURIComponent(escape(window.atob(str)));
  }
}

function rootController($scope, $route, $routeParams, $location, Toma){
  $scope.createLink = function(){
    $scope.lincoln = $scope.docRoot + 'img?url=' + $scope.utf8ToBase64($scope.imageUrl) + '&fl=' + $scope.utf8ToBase64($scope.firstLine) + '&sl=' + $scope.utf8ToBase64($scope.secondLine)
  };

  var lasCosas = Toma.getMemeData();

  $scope.imageUrl = lasCosas.imageUrl;
  $scope.firstLine = lasCosas.firstLine;
  $scope.secondLine = lasCosas.secondLine;

  $scope.autoSelect = function($event){
    $event.currentTarget.select();
  }

  $scope.imageWidth = {
    'width' : 'auto'
  };
}

function imageController($scope, $route, $routeParams, $location, Toma){
  $scope.imageUrl = $scope.b64ToUtf8($routeParams.url);
  $scope.firstLine = $scope.b64ToUtf8($routeParams.fl);
  $scope.secondLine = $scope.b64ToUtf8($routeParams.sl);

  var dataMagica = {
    'imageUrl' : $scope.imageUrl,
    'firstLine' : $scope.firstLine,
    'secondLine' : $scope.secondLine
  };

  Toma.setMemeData(dataMagica)
}

/* End Controllers */

/* Directives
 * ========================================= */

ngMeme.directive('cradle', function(){
  return function(scope, element, attrs){
    element.bind('load', function(e){
      var width = element[0].width;
      var ems = width / 677;
      scope.imageWidth = {
        'width' : width + 'px',
        'font-size' : ems + 'em'
      };
      scope.$apply();
    });
  }
});

/* End Directives */

/* Filters
 * ========================================= */

/* End Filters */

/* Services
 * ========================================= */

ngMeme.factory('Toma', function(){
  var memeData = {
    'imageUrl' : '',
    'firstLine' : '',
    'secondLine' : ''
  };

  return {
    getMemeData : function(){
      return memeData;
    },
    setMemeData : function(data){
      memeData = data;
    }
  }
})

/* End Services */

/* x
 * ========================================= */

/* End x */
<commit_msg>Autoselect share input on clicking, swap select for setSelectionRange to appease ios<commit_after>'use strict';

/* App module
 * ========================================= */

var ngMeme = angular.module('ngMeme', [])

ngMeme.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider){
    $routeProvider.when('/', {
      templateUrl: 'partials/root.html',
      controller: rootController
    });
    $routeProvider.when('/img:params', {
      templateUrl: 'partials/image.html',
      controller: imageController
    });
    $routeProvider.otherwise({
      redirectTo: '/'
    });
  }]);

/* End App module */

/* Controllers
 * ========================================= */

function mainController($scope, $route, $routeParams, $location, Toma){
  $scope.$route = $route;
  $scope.$location = $location;
  $scope.$routeParams = $routeParams;
  $scope.docRoot = window.location.origin + '/meme/#/';

  $scope.memeAreaHeight = function(chromeHeight){
    var windowHeight = window.innerHeight;
    var areaHeight = (windowHeight - chromeHeight) + 'px';
    return {'height' : areaHeight};
  }

  $scope.utf8ToBase64 = function(str){
    return window.btoa(unescape(encodeURIComponent(str))).replace(/=+$/, '');
  }
  $scope.b64ToUtf8 = function(str){
    return decodeURIComponent(escape(window.atob(str)));
  }
}

function rootController($scope, $route, $routeParams, $location, Toma){
  $scope.createLink = function(){
    $scope.lincoln = $scope.docRoot + 'img?url=' + $scope.utf8ToBase64($scope.imageUrl) + '&fl=' + $scope.utf8ToBase64($scope.firstLine) + '&sl=' + $scope.utf8ToBase64($scope.secondLine);
    setTimeout(function(){
      document.querySelector('.share-field input').select();
    }, 100);
  };

  var lasCosas = Toma.getMemeData();

  $scope.imageUrl = lasCosas.imageUrl;
  $scope.firstLine = lasCosas.firstLine;
  $scope.secondLine = lasCosas.secondLine;

  $scope.autoSelect = function($event){
    $event.currentTarget.setSelectionRange(0,7777777);
  }

  $scope.imageWidth = {
    'width' : 'auto'
  };
}

function imageController($scope, $route, $routeParams, $location, Toma){
  $scope.imageUrl = $scope.b64ToUtf8($routeParams.url);
  $scope.firstLine = $scope.b64ToUtf8($routeParams.fl);
  $scope.secondLine = $scope.b64ToUtf8($routeParams.sl);

  var dataMagica = {
    'imageUrl' : $scope.imageUrl,
    'firstLine' : $scope.firstLine,
    'secondLine' : $scope.secondLine
  };

  Toma.setMemeData(dataMagica)
}

/* End Controllers */

/* Directives
 * ========================================= */

ngMeme.directive('cradle', function(){
  return function(scope, element, attrs){
    element.bind('load', function(e){
      var width = element[0].width;
      var ems = width / 677;
      scope.imageWidth = {
        'width' : width + 'px',
        'font-size' : ems + 'em'
      };
      scope.$apply();
    });
  }
});

/* End Directives */

/* Filters
 * ========================================= */

/* End Filters */

/* Services
 * ========================================= */

ngMeme.factory('Toma', function(){
  var memeData = {
    'imageUrl' : '',
    'firstLine' : '',
    'secondLine' : ''
  };

  return {
    getMemeData : function(){
      return memeData;
    },
    setMemeData : function(data){
      memeData = data;
    }
  }
})

/* End Services */

/* x
 * ========================================= */

/* End x */
<|endoftext|>


<commit_before>
var gulp = require('gulp');
var config = {
    directory: './site/',
    css: [
        "css/site.css",
        "node_modules/highlight.js/styles/monokai_sublime.css"
    ],
    icons: "node_modules/geomicons-open/icons/*.svg",
    images: {
        thumbnails: [626]
    }
};

function pages() {

    var nunjucks = require('static-engine-renderer-nunjucks');
    var engine = require('static-engine');
    var content = require('static-engine-content');
    var defaults = require('static-engine-defaults');
    var pager = require('static-engine-pager');
    var first = require('static-engine-first');
    var collection = require('static-engine-collection');
    var marked = require('static-engine-converter-marked');
    var file = require('static-engine-converter-file');
    var frontmatter = require('static-engine-converter-frontmatter');
    var render = require('static-engine-render');
    var sort = require('static-engine-sort');
    var compose = require('static-compose');
    var hljs = require('highlight.js');
    var cson = require('cson-parser');
    var posts;
    var post_pages, archive_page, _404_page;
    var converters;

    nunjucks.configure('./templates/', {
        autoescape: true
    });

    converters = [
        file,
        frontmatter(cson.parse),
        marked({
            highlight: function(code) {

                return hljs.highlightAuto(code).value;
            }
        })
    ];

    posts = compose(content('./content/posts/*', converters), sort.date);

    defaults = defaults('./content/defaults.cson', cson.parse);

    post_pages = [
        posts,
        pager,
        defaults,
        render(config.directory + 'posts/:slug/index.html', nunjucks('post.html')),
        first,
        render(config.directory + 'index.html', nunjucks('post.html'))
    ];

    archive_page = [
        content('./content/posts.md', converters),
        collection('posts', posts),
        defaults,
        render(config.directory + 'posts/index.html', nunjucks('posts.html'))
    ];

    _404_page = [
        content('./content/404.md', converters),
        defaults,
        render(config.directory + '404.html', nunjucks('404.html'))
    ];

    return engine(post_pages, archive_page, _404_page);
}

function base(){

    return gulp.src('base/**').pipe(gulp.dest(config.directory));
}

function css(){

    var autoprefixer = require('gulp-autoprefixer');
    var uncss = require('gulp-uncss');
    var csso = require('gulp-csso');
    var glob = require('glob');
    var rework = require('gulp-rework');
    var concat = require('gulp-concat');
    var calc = require('rework-calc');
    var media = require('rework-custom-media');
    var npm = require('rework-npm');
    var vars = require('rework-vars');
    var colors = require('rework-plugin-colors');

    var stream = gulp.src(config.css)
        .pipe(rework(
            npm(),
            vars(),
            media(),
            calc,
            colors()
        ))
        .pipe(autoprefixer('> 1%', 'last 2 versions'))
        .pipe(concat("index.css"))
        .pipe(uncss({
            html: glob.sync(config.directory + '**/**.html')
        }))
        .pipe(csso());

    return stream.pipe(gulp.dest(config.directory));
}

function combine(done) {

    var path = require('path');
    var tap = require('gulp-tap');
    var csso = require('gulp-csso');
    var cheerio = require('gulp-cheerio');
    var glob = require('glob');
    var htmls = glob.sync(config.directory + '**/**.html');
    var uncss = require('gulp-uncss');
    var end = require('stream-end');
    var inline = function(html, next) {

        return gulp.src(config.directory + 'index.css')
            .pipe(uncss({
                html: [html]
            }))
            .pipe(csso())
            .pipe(tap(function(file){

                gulp.src([html])
                    .pipe(cheerio(function($){

                        $('head').append('<style type="text/css">'+file.contents.toString()+'</style>');

                    }))
                    .pipe(gulp.dest(path.dirname(html)))
                    .pipe(end(next));
            }))
    };
    var next = function(){

        if(htmls.length) {

            inline(htmls.shift(), next);
        }
        else {

            done();
        }
    };

    inline(htmls.shift(), next);
}

function optimize(){

    var htmlmin = require('gulp-htmlmin');

    return gulp.src(config.directory + '**/**.html')
        .pipe(htmlmin({
            collapseWhitespace: true
        }))
        .pipe(gulp.dest(config.directory));
}

function icons() {

    var cheerio = require('gulp-cheerio');
    var concat = require('gulp-concat');
    var tap = require('gulp-tap');
    var clean = require('gulp-htmlclean');

    return gulp.src(config.icons)
    .pipe(cheerio(function ($) {
        var $path = $('svg').children('path');
        var id = $('svg').attr('id');
        $path.attr('id', id);
        $('svg').replaceWith($path[0]);
    }))
    .pipe(concat('icons.svg'))
    .pipe(tap(function(file){

        return gulp.src(config.directory + '**/**.html')
        .pipe(cheerio(function($){

            var defs = $('<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0"><defs>'+file.contents+'</defs></svg>');
            var uses = [];

            $('body').append(defs);

            $('use').each(function(){

                uses.push($(this).attr('xlink:href'));
            });

            $('use').each(function(){

                var el = $(this);
                var href = el.attr('xlink:href');
                var index = uses.indexOf(href);

                if(index == uses.lastIndexOf(href)) {

                    el.replaceWith($.html('path'+href));

                    uses.splice(index, 1);
                }
            });

            $('defs path[id]').each(function(){

                var el = $(this);

                if(uses.indexOf('#'+el.attr('id')) < 0) {

                    el.replaceWith('');
                }
            });

            $('defs').filter(function(){

                return !$(this).find('path').length;

            }).parent().remove();
        }))
        .pipe(clean())
        .pipe(gulp.dest(config.directory));
    }));
}

function images() {

    var imageresize = require('gulp-image-resize');
    var changed = require('gulp-changed');
    var imagemin = require('gulp-imagemin');
    var merge = require('merge-stream');
    var image;
    var directory;
    var merged;

    var stream = gulp.src('content/uploads/*.jpg')
        .pipe(changed(config.directory + 'uploads'))
        .pipe(imagemin({
            progressive: true
        }))
        .pipe(gulp.dest(config.directory + 'uploads'));

    merged = merge(stream);

    for(directory in config.images) {

        image = config.images[directory];

        if(!image[0] && !image[1]) return;

        stream = gulp.src('content/uploads/*.jpg')
            .pipe(changed(config.directory + 'uploads'))
            .pipe(imageresize({
                width: image[0] || 0,
                height: image[1] || 0,
                imageMagick: true
            }))
            .pipe(imagemin({
                progressive: true
            }))
            .pipe(gulp.dest(config.directory + 'uploads/' + directory));

        merged.add(stream);
    }

    return merged;
}

function watch() {

    gulp.watch('base/**/*', base);
    gulp.watch('content/uploads/**/*.jpg', images);
    gulp.watch('css/**/*.css', 'default');
    gulp.watch(['templates/**/*.html', 'content/**/*.md'], gulp.series(pages, optimize, icons, css));
}

function serve(done){

    var express = require('express');
    var static = require('express-static');
    var logger = require('express-log');
    var fs = require('fs');
    var path = require('path');

    var app = express();

    app.use(logger());

    app.use(static(config.directory));

    app.use(function(req, res, next){
        res.status(404);

        if (req.accepts('html') && fs.existsSync(config.directory + '404.html')) {
            res.sendFile(path.resolve(config.directory, '404.html'));

            return;
        }

        res.type('txt').send('Not found');
    });

    var server = app.listen(8088, function(){
        console.log('server is running at %s', server.address().port);
    });

    done();
}

gulp.task('default', gulp.parallel(base, gulp.series(pages, optimize, icons, css, combine), images));

gulp.task('dev', gulp.parallel('default', watch, serve));
<commit_msg>Add semicolon<commit_after>
var gulp = require('gulp');
var config = {
    directory: './site/',
    css: [
        "css/site.css",
        "node_modules/highlight.js/styles/monokai_sublime.css"
    ],
    icons: "node_modules/geomicons-open/icons/*.svg",
    images: {
        thumbnails: [626]
    }
};

function pages() {

    var nunjucks = require('static-engine-renderer-nunjucks');
    var engine = require('static-engine');
    var content = require('static-engine-content');
    var defaults = require('static-engine-defaults');
    var pager = require('static-engine-pager');
    var first = require('static-engine-first');
    var collection = require('static-engine-collection');
    var marked = require('static-engine-converter-marked');
    var file = require('static-engine-converter-file');
    var frontmatter = require('static-engine-converter-frontmatter');
    var render = require('static-engine-render');
    var sort = require('static-engine-sort');
    var compose = require('static-compose');
    var hljs = require('highlight.js');
    var cson = require('cson-parser');
    var posts;
    var post_pages, archive_page, _404_page;
    var converters;

    nunjucks.configure('./templates/', {
        autoescape: true
    });

    converters = [
        file,
        frontmatter(cson.parse),
        marked({
            highlight: function(code) {

                return hljs.highlightAuto(code).value;
            }
        })
    ];

    posts = compose(content('./content/posts/*', converters), sort.date);

    defaults = defaults('./content/defaults.cson', cson.parse);

    post_pages = [
        posts,
        pager,
        defaults,
        render(config.directory + 'posts/:slug/index.html', nunjucks('post.html')),
        first,
        render(config.directory + 'index.html', nunjucks('post.html'))
    ];

    archive_page = [
        content('./content/posts.md', converters),
        collection('posts', posts),
        defaults,
        render(config.directory + 'posts/index.html', nunjucks('posts.html'))
    ];

    _404_page = [
        content('./content/404.md', converters),
        defaults,
        render(config.directory + '404.html', nunjucks('404.html'))
    ];

    return engine(post_pages, archive_page, _404_page);
}

function base(){

    return gulp.src('base/**').pipe(gulp.dest(config.directory));
}

function css(){

    var autoprefixer = require('gulp-autoprefixer');
    var uncss = require('gulp-uncss');
    var csso = require('gulp-csso');
    var glob = require('glob');
    var rework = require('gulp-rework');
    var concat = require('gulp-concat');
    var calc = require('rework-calc');
    var media = require('rework-custom-media');
    var npm = require('rework-npm');
    var vars = require('rework-vars');
    var colors = require('rework-plugin-colors');

    var stream = gulp.src(config.css)
        .pipe(rework(
            npm(),
            vars(),
            media(),
            calc,
            colors()
        ))
        .pipe(autoprefixer('> 1%', 'last 2 versions'))
        .pipe(concat("index.css"))
        .pipe(uncss({
            html: glob.sync(config.directory + '**/**.html')
        }))
        .pipe(csso());

    return stream.pipe(gulp.dest(config.directory));
}

function combine(done) {

    var path = require('path');
    var tap = require('gulp-tap');
    var csso = require('gulp-csso');
    var cheerio = require('gulp-cheerio');
    var glob = require('glob');
    var htmls = glob.sync(config.directory + '**/**.html');
    var uncss = require('gulp-uncss');
    var end = require('stream-end');
    var inline = function(html, next) {

        return gulp.src(config.directory + 'index.css')
            .pipe(uncss({
                html: [html]
            }))
            .pipe(csso())
            .pipe(tap(function(file){

                gulp.src([html])
                    .pipe(cheerio(function($){

                        $('head').append('<style type="text/css">'+file.contents.toString()+'</style>');

                    }))
                    .pipe(gulp.dest(path.dirname(html)))
                    .pipe(end(next));
            }));
    };
    var next = function(){

        if(htmls.length) {

            inline(htmls.shift(), next);
        }
        else {

            done();
        }
    };

    inline(htmls.shift(), next);
}

function optimize(){

    var htmlmin = require('gulp-htmlmin');

    return gulp.src(config.directory + '**/**.html')
        .pipe(htmlmin({
            collapseWhitespace: true
        }))
        .pipe(gulp.dest(config.directory));
}

function icons() {

    var cheerio = require('gulp-cheerio');
    var concat = require('gulp-concat');
    var tap = require('gulp-tap');
    var clean = require('gulp-htmlclean');

    return gulp.src(config.icons)
    .pipe(cheerio(function ($) {
        var $path = $('svg').children('path');
        var id = $('svg').attr('id');
        $path.attr('id', id);
        $('svg').replaceWith($path[0]);
    }))
    .pipe(concat('icons.svg'))
    .pipe(tap(function(file){

        return gulp.src(config.directory + '**/**.html')
        .pipe(cheerio(function($){

            var defs = $('<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0"><defs>'+file.contents+'</defs></svg>');
            var uses = [];

            $('body').append(defs);

            $('use').each(function(){

                uses.push($(this).attr('xlink:href'));
            });

            $('use').each(function(){

                var el = $(this);
                var href = el.attr('xlink:href');
                var index = uses.indexOf(href);

                if(index == uses.lastIndexOf(href)) {

                    el.replaceWith($.html('path'+href));

                    uses.splice(index, 1);
                }
            });

            $('defs path[id]').each(function(){

                var el = $(this);

                if(uses.indexOf('#'+el.attr('id')) < 0) {

                    el.replaceWith('');
                }
            });

            $('defs').filter(function(){

                return !$(this).find('path').length;

            }).parent().remove();
        }))
        .pipe(clean())
        .pipe(gulp.dest(config.directory));
    }));
}

function images() {

    var imageresize = require('gulp-image-resize');
    var changed = require('gulp-changed');
    var imagemin = require('gulp-imagemin');
    var merge = require('merge-stream');
    var image;
    var directory;
    var merged;

    var stream = gulp.src('content/uploads/*.jpg')
        .pipe(changed(config.directory + 'uploads'))
        .pipe(imagemin({
            progressive: true
        }))
        .pipe(gulp.dest(config.directory + 'uploads'));

    merged = merge(stream);

    for(directory in config.images) {

        image = config.images[directory];

        if(!image[0] && !image[1]) return;

        stream = gulp.src('content/uploads/*.jpg')
            .pipe(changed(config.directory + 'uploads'))
            .pipe(imageresize({
                width: image[0] || 0,
                height: image[1] || 0,
                imageMagick: true
            }))
            .pipe(imagemin({
                progressive: true
            }))
            .pipe(gulp.dest(config.directory + 'uploads/' + directory));

        merged.add(stream);
    }

    return merged;
}

function watch() {

    gulp.watch('base/**/*', base);
    gulp.watch('content/uploads/**/*.jpg', images);
    gulp.watch('css/**/*.css', 'default');
    gulp.watch(['templates/**/*.html', 'content/**/*.md'], gulp.series(pages, optimize, icons, css));
}

function serve(done){

    var express = require('express');
    var static = require('express-static');
    var logger = require('express-log');
    var fs = require('fs');
    var path = require('path');

    var app = express();

    app.use(logger());

    app.use(static(config.directory));

    app.use(function(req, res, next){
        res.status(404);

        if (req.accepts('html') && fs.existsSync(config.directory + '404.html')) {
            res.sendFile(path.resolve(config.directory, '404.html'));

            return;
        }

        res.type('txt').send('Not found');
    });

    var server = app.listen(8088, function(){
        console.log('server is running at %s', server.address().port);
    });

    done();
}

gulp.task('default', gulp.parallel(base, gulp.series(pages, optimize, icons, css, combine), images));

gulp.task('dev', gulp.parallel('default', watch, serve));
<|endoftext|>


<commit_before>/**
 * Copyright 2017 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// [START presence_sync_function]
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

// Since this code will be running in the Cloud Functions enviornment
// we call initialize Firestore without any arguments because it
// detects authentication from the environment.
const firestore = admin.firestore();

// Create a new function which is triggered on changes to /status/{uid}
// Note: This is a Realtime Database trigger, *not* Cloud Firestore.
exports.onUserStatusChanged = functions.database.ref('/status/{uid}').onUpdate(
    async (change, context) => {
      // Get the data written to Realtime Database
      const eventStatus = change.after.val();

      // Then use other event data to create a reference to the
      // corresponding Firestore document.
      const userStatusFirestoreRef = firestore.doc(`status/${context.params.uid}`);

      // It is likely that the Realtime Database change that triggered
      // this event has already been overwritten by a fast change in
      // online / offline status, so we'll re-read the current data
      // and compare the timestamps.
      const statusSnapshot = await change.after.ref.once('value');
      const status = statusSnapshot.val();
      console.log(status, eventStatus);
      // If the current timestamp for this data is newer than
      // the data that triggered this event, we exit this function.
      if (status.last_changed > eventStatus.last_changed) {
        return null;
      }

      // Otherwise, we convert the last_changed field to a Date
      eventStatus.last_changed = new Date(eventStatus.last_changed);

      // ... and write it to Firestore.
      return userStatusFirestoreRef.set(eventStatus);
    });
// [END presence_sync_function]
<commit_msg>enviornment -> environment<commit_after>/**
 * Copyright 2017 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// [START presence_sync_function]
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

// Since this code will be running in the Cloud Functions environment
// we call initialize Firestore without any arguments because it
// detects authentication from the environment.
const firestore = admin.firestore();

// Create a new function which is triggered on changes to /status/{uid}
// Note: This is a Realtime Database trigger, *not* Cloud Firestore.
exports.onUserStatusChanged = functions.database.ref('/status/{uid}').onUpdate(
    async (change, context) => {
      // Get the data written to Realtime Database
      const eventStatus = change.after.val();

      // Then use other event data to create a reference to the
      // corresponding Firestore document.
      const userStatusFirestoreRef = firestore.doc(`status/${context.params.uid}`);

      // It is likely that the Realtime Database change that triggered
      // this event has already been overwritten by a fast change in
      // online / offline status, so we'll re-read the current data
      // and compare the timestamps.
      const statusSnapshot = await change.after.ref.once('value');
      const status = statusSnapshot.val();
      console.log(status, eventStatus);
      // If the current timestamp for this data is newer than
      // the data that triggered this event, we exit this function.
      if (status.last_changed > eventStatus.last_changed) {
        return null;
      }

      // Otherwise, we convert the last_changed field to a Date
      eventStatus.last_changed = new Date(eventStatus.last_changed);

      // ... and write it to Firestore.
      return userStatusFirestoreRef.set(eventStatus);
    });
// [END presence_sync_function]
<|endoftext|>