<commit_before>/**
 * App ID for the skill
 */
//var APP_ID = undefined; //OPTIONAL: replace with "amzn1.echo-sdk-ams.app.[your-unique-value-here]";

var APP_ID = "amzn1.ask.skill.69248e8b-2456-4937-9227-94773ceb34de";

// [http://www.chimet.co.uk/csg/chi.html]
// `22 January,6:50 am,6.4,7.4,051,3.90, 0.59,0.68,15,1.6,,1026,`
// Date, time, mean, gust, Wind Dir, tide hight, mean wave height, max wave height, wave period, air temp, sea temp, pressure, visibility

var URI = 'http://www.chimet.co.uk/csg/chi.html';
var http = require('http');
var chiData = [];
var chiDataTime = 0;

/**
 * The AlexaSkill prototype and helper functions
 */
var AlexaSkill = require('./AlexaSkill');

/**
 * SpaceGeek is a child of AlexaSkill.
 * To read more about inheritance in JavaScript, see the link below.
 *
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript#Inheritance
 */
var Chimet = function () {
    AlexaSkill.call(this, APP_ID);
};

// Extend AlexaSkill
Chimet.prototype = Object.create(AlexaSkill.prototype);
Chimet.prototype.constructor = Chimet;

Chimet.prototype.eventHandlers.onSessionStarted = function (sessionStartedRequest, session) {
    //console.log("onSessionStarted requestId: " + sessionStartedRequest.requestId + ", sessionId: " + session.sessionId);
    // any initialization logic goes here
};

Chimet.prototype.eventHandlers.onLaunch = function (launchRequest, session, response) {
    //console.log("onLaunch requestId: " + launchRequest.requestId + ", sessionId: " + session.sessionId);
    handleNewFactRequest(response);
};

/**
 * Overridden to show that a subclass can override this function to teardown session state.
 */
Chimet.prototype.eventHandlers.onSessionEnded = function (sessionEndedRequest, session) {
    //console.log("onSessionEnded requestId: " + sessionEndedRequest.requestId + ", sessionId: " + session.sessionId);
    // any cleanup logic goes here
};

Chimet.prototype.intentHandlers = {
    "GetChiMetIntent": function (intent, session, response) {
	    console.log("Chimet.prototype.intentHandlers: got here!");
		handleChiMetRequest(response);
    },

    "AMAZON.HelpIntent": function (intent, session, response) {
        response.ask("What can I help you with?");
    },

    "AMAZON.StopIntent": function (intent, session, response) {
        var speechOutput = "Goodbye";
        response.tell(speechOutput);
    },

    "AMAZON.CancelIntent": function (intent, session, response) {
        var speechOutput = "Goodbye";
        response.tell(speechOutput);
    }
};

/**
 * Gets a random new fact from the list and returns to the user.
 */

function handleChiMetRequest(response) {

  console.log('handleChiMetRequest: got here too');
  var speechOutput = '';
  var cardTitle = 'Chimet';

  console.time('http-request');

  http.get(URI, function (res) {
    var chiResponseString = '';
    console.log('handleChiMetRequest: HTTP response for Status Code: '+res.statusCode+', for: '+URI);

    // if for some reason we did not get a HTTP 200 OK
    if (res.statusCode != 200) {
      forecastResponseCallback(new Error("handleChiMetRequest: Non 200 Response for: "+URI));
      console.timeEnd('http-request');
    }

    // got some more data to append
    res.on('data', function (data) {
      chiResponseString += data;
    });

    // in theory finished!
    res.on('end', function () {
      // should have a sensible result
      chiDataTime = new Date().getTime();
      chiData = chiResponseString.split(',');
      console.log("handleChiMetRequest: res.on done");
      console.timeEnd('http-request');

      speechOutput = 'Chimet.  '+chiData[1]+'.  '+chiData[0]+'.  '
        +'Wind mean '+chiData[2]+', gusting '+chiData[3]+', direction '+chiData[4]+'.  '
        +'Tide height '+chiData[5]+'.  '
        +'Air temp '+chiData[9]+' degrees.';

	  console.log("handleChiMetRequest: speechOutput is: "+speechOutput);

    });
  }).on('error', function (e) {
    console.timeEnd('http-request');
    console.log("handleChiMetRequest: Communications error: " + e.message);
  });

  console.log('handleChiMetRequest: speechOutput is: '+speechOutput);
  response.tellWithCard(speechOutput, cardTitle, speechOutput);
}

// Create the handler that responds to the Alexa Request.
exports.handler = function (event, context) {
    var chimet = new Chimet();
    // Create an instance of the chimet skill.
    chimet.execute(event, context);
};

<commit_msg>build commit: 1485094028<commit_after>/**
 * App ID for the skill
 */
//var APP_ID = undefined; //OPTIONAL: replace with "amzn1.echo-sdk-ams.app.[your-unique-value-here]";

var APP_ID = "amzn1.ask.skill.69248e8b-2456-4937-9227-94773ceb34de";

// [http://www.chimet.co.uk/csg/chi.html]
// `22 January,6:50 am,6.4,7.4,051,3.90, 0.59,0.68,15,1.6,,1026,`
// Date, time, mean, gust, Wind Dir, tide hight, mean wave height, max wave height, wave period, air temp, sea temp, pressure, visibility

var URI = 'http://www.chimet.co.uk/csg/chi.html';
var http = require('http');
var chiData = [];
var chiDataTime = 0;

/**
 * The AlexaSkill prototype and helper functions
 */
var AlexaSkill = require('./AlexaSkill');

/**
 * SpaceGeek is a child of AlexaSkill.
 * To read more about inheritance in JavaScript, see the link below.
 *
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript#Inheritance
 */
var Chimet = function () {
    AlexaSkill.call(this, APP_ID);
};

// Extend AlexaSkill
Chimet.prototype = Object.create(AlexaSkill.prototype);
Chimet.prototype.constructor = Chimet;

Chimet.prototype.eventHandlers.onSessionStarted = function (sessionStartedRequest, session) {
    //console.log("onSessionStarted requestId: " + sessionStartedRequest.requestId + ", sessionId: " + session.sessionId);
    // any initialization logic goes here
};

Chimet.prototype.eventHandlers.onLaunch = function (launchRequest, session, response) {
    //console.log("onLaunch requestId: " + launchRequest.requestId + ", sessionId: " + session.sessionId);
    handleNewFactRequest(response);
};

/**
 * Overridden to show that a subclass can override this function to teardown session state.
 */
Chimet.prototype.eventHandlers.onSessionEnded = function (sessionEndedRequest, session) {
    //console.log("onSessionEnded requestId: " + sessionEndedRequest.requestId + ", sessionId: " + session.sessionId);
    // any cleanup logic goes here
};

Chimet.prototype.intentHandlers = {
    "GetChiMetIntent": function (intent, session, response) {
	    console.log("Chimet.prototype.intentHandlers: got here!");
		handleChiMetRequest(response);
    },

    "AMAZON.HelpIntent": function (intent, session, response) {
        response.ask("What can I help you with?");
    },

    "AMAZON.StopIntent": function (intent, session, response) {
        var speechOutput = "Goodbye";
        response.tell(speechOutput);
    },

    "AMAZON.CancelIntent": function (intent, session, response) {
        var speechOutput = "Goodbye";
        response.tell(speechOutput);
    }
};

/**
 * Gets a random new fact from the list and returns to the user.
 */

function handleChiMetRequest(response) {

  console.log('handleChiMetRequest: got here too');
  var speechOutput = '';
  var cardTitle = 'Chimet';

  console.time('http-request');

  console.log('about to start HTTP request for: '+URI);
  http.get(URI, function (res) {
    var chiResponseString = '';
    console.log('handleChiMetRequest: HTTP response for Status Code: '+res.statusCode+', for: '+URI);

    // if for some reason we did not get a HTTP 200 OK
    if (res.statusCode != 200) {
	  console.log("handleChiMetRequest: Non 200 Response for: "+URI);
      forecastResponseCallback(new Error("handleChiMetRequest: Non 200 Response for: "+URI));
      console.timeEnd('http-request');
    }

    // got some more data to append
    res.on('data', function (data) {
      chiResponseString += data;
    });

    // in theory finished!
    res.on('end', function () {
      // should have a sensible result
      chiDataTime = new Date().getTime();
      chiData = chiResponseString.split(',');
      console.log("handleChiMetRequest: res.on done");
      console.timeEnd('http-request');

      speechOutput = 'Chimet.  '+chiData[1]+'.  '+chiData[0]+'.  '
        +'Wind mean '+chiData[2]+', gusting '+chiData[3]+', direction '+chiData[4]+'.  '
        +'Tide height '+chiData[5]+'.  '
        +'Air temp '+chiData[9]+' degrees.';

	  console.log("handleChiMetRequest: speechOutput is: "+speechOutput);

    });
  }).on('error', function (e) {
    console.timeEnd('http-request');
    console.log("handleChiMetRequest: Communications error: " + e.message);
  });

  console.log('handleChiMetRequest: speechOutput is: '+speechOutput);
  response.tellWithCard(speechOutput, cardTitle, speechOutput);
}

// Create the handler that responds to the Alexa Request.
exports.handler = function (event, context) {
    var chimet = new Chimet();
    // Create an instance of the chimet skill.
    chimet.execute(event, context);
};

<|endoftext|>


<commit_before>import {
  observe as doObserve,
  defineReactive,
} from './observe'
import {
  watch as doWatch,
  makeComputed,
} from './watcher'
import {
  defineValue,
  defineAccessor,
  noop,
  isFunction,
  everyEntries,
} from './util'
import {
  WATCHERS_PROPERTY_NAME,
  DATA_PROPTERTY_NAME,
} from './constants'

Object.defineProperties(observe, {
  'react': {value: react},
  'compute': {value: compute},
  'watch': {value: watch},
  'default': {value: watch, writable: true}, // Only could be react, compute or watch
  'deep': {value: false, writable: true},
  'lazy': {value: false, writable: true},
  'sync': {value: false, writable: true},
})

/**
 * observe
 *
 * @public
 * @param {Object} target
 * @param {*} [expression]
 * @param {*} [func]
 * @param {*} [options]
 * @return {Function} observe
 */

export default function observe (target, expression, func, options) {
  if (!target.hasOwnProperty(WATCHERS_PROPERTY_NAME)) {
    init(target)
  }
  return observe.default(target, expression, func, options)
}

/**
 * React options
 *
 * @param {Object} options
 * @param {Object} [target]
 * @return {Function} observe
 */

function react (options, target) {
  if (target) {
    if (!target.hasOwnProperty(WATCHERS_PROPERTY_NAME)) {
      init(target)
    }
  } else {
    target = {}
    init(target)
  }
  options.methods && carryMethods(target, options.methods)
  options.data && reactProperties(target, options.data)
  options.computed && computeProperties(target, options.computed)
  options.watchers && watchProperties(target, options.watchers)
  return target
}

/**
 * Compute property
 *
 * @param {Object} target
 * @param {String} name
 * @param {Function|Object} getterOrAccessor
 *        - Function getter
 *        - Object accessor
 *          - Function [get]  - getter
 *          - Function [set]  - setter
 *          - Boolean [cache]
 * @param {Boolean} [cache]
 */

function compute (target, name, getterOrAccessor, cache) {
  if (!target.hasOwnProperty(WATCHERS_PROPERTY_NAME)) {
    init(target)
  }
  let getter, setter
  if (isFunction(getterOrAccessor)) {
    getter = cache !== false
            ? makeComputed(target, getterOrAccessor)
            : getterOrAccessor.bind(this)
    setter = noop
  } else {
    getter = getterOrAccessor.get
            ? getterOrAccessor.cache !== false || cache !== false
              ? makeComputed(target, getterOrAccessor.get)
              : getterOrAccessor.get.bind(this)
            : noop
    setter = getterOrAccessor.set ? getterOrAccessor.set.bind(this) : noop
  }
  defineAccessor(target, name, getter, setter)
}

/**
 * Watch property
 *
 * @param {Object} target
 * @param {String|Function} expressionOrFunction
 * @param {Function} callback
 * @param {Object} [options]
 *                 - {Boolean} deep
 *                 - {Boolean} sync
 *                 - {Boolean} lazy
 * @return {Watcher}
 */

function watch (target, expressionOrFunction, callback, options = observe) {
  if (!target.hasOwnProperty(WATCHERS_PROPERTY_NAME)) {
    init(target)
  }
  return doWatch(target, expressionOrFunction, callback, options)
}

/**
 * @param {Object} target
 */

function init (target) {
  defineValue(target, WATCHERS_PROPERTY_NAME, [], false)
  defineValue(target, DATA_PROPTERTY_NAME, Object.create(null), false)
  doObserve(target[DATA_PROPTERTY_NAME])
  reactSelfProperties(target)
}

/**
 * @param {Object} target
 * @param {Object} methods
 */

function carryMethods (target, methods) {
  everyEntries(methods, (name, method) => {
    target[name] = method.bind(target)
  })
}

/**
 * @param {Object} target
 * @param {String} key
 * @param {*} value
 */

function reactProperty (target, key, value) {
  target[DATA_PROPTERTY_NAME][key] = value
  defineReactive(target[DATA_PROPTERTY_NAME], key, value)
  proxy(target, key)
}

/**
 * @param {Object} target
 * @param {Object} properties
 */

function reactProperties (target, properties) {
  everyEntries(properties, (key, value) => reactProperty(target, key, value))
}

/**
 * @param {Object} target
 */

function reactSelfProperties (target) {
  everyEntries(target, (key, value) => {
    !isFunction(value) && reactProperty(target, key, value)
  })
}

/**
 * @param {Object} target
 * @param {Object} properties
 */

function computeProperties (target, properties) {
  everyEntries(properties, (key, value) => compute(target, key, value))
}

/**
 * @param {Object} target
 * @param {Object} properties
 */

function watchProperties (target, properties) {
  everyEntries(properties, (expression, functionOrOption) => {
    if (isFunction(functionOrOption)) {
      watch(target, expression, functionOrOption)
    } else {
      watch(target, expression, functionOrOption.watcher, functionOrOption)
    }
  })
}

/**
 * @param {Object} target
 * @param {String} key
 */

function proxy (target, key) {
  function getter () {
    return target[DATA_PROPTERTY_NAME][key]
  }
  function setter (value) {
    target[DATA_PROPTERTY_NAME][key] = value
  }
  defineAccessor(target, key, getter, setter)
}
<commit_msg>Use Object.prototype.hasOwnProperty instead of target.hasOwnProperty<commit_after>import {
  observe as doObserve,
  defineReactive,
} from './observe'
import {
  watch as doWatch,
  makeComputed,
} from './watcher'
import {
  defineValue,
  defineAccessor,
  noop,
  isFunction,
  everyEntries,
} from './util'
import {
  WATCHERS_PROPERTY_NAME,
  DATA_PROPTERTY_NAME,
} from './constants'

Object.defineProperties(observe, {
  'react': {value: react},
  'compute': {value: compute},
  'watch': {value: watch},
  'default': {value: watch, writable: true}, // Only could be react, compute or watch
  'deep': {value: false, writable: true},
  'lazy': {value: false, writable: true},
  'sync': {value: false, writable: true},
})

/**
 * observe
 *
 * @public
 * @param {Object} target
 * @param {*} [expression]
 * @param {*} [func]
 * @param {*} [options]
 * @return {Function} observe
 */

export default function observe (target, expression, func, options) {
  ensure(target)
  return observe.default(target, expression, func, options)
}

/**
 * React options
 *
 * @param {Object} options
 * @param {Object} [target]
 * @return {Function} observe
 */

function react (options, target) {
  if (target) {
    ensure(target)
  } else {
    target = {}
    init(target)
  }
  options.methods && carryMethods(target, options.methods)
  options.data && reactProperties(target, options.data)
  options.computed && computeProperties(target, options.computed)
  options.watchers && watchProperties(target, options.watchers)
  return target
}

/**
 * Compute property
 *
 * @param {Object} target
 * @param {String} name
 * @param {Function|Object} getterOrAccessor
 *        - Function getter
 *        - Object accessor
 *          - Function [get]  - getter
 *          - Function [set]  - setter
 *          - Boolean [cache]
 * @param {Boolean} [cache]
 */

function compute (target, name, getterOrAccessor, cache) {
  ensure(target)
  let getter, setter
  if (isFunction(getterOrAccessor)) {
    getter = cache !== false
            ? makeComputed(target, getterOrAccessor)
            : getterOrAccessor.bind(this)
    setter = noop
  } else {
    getter = getterOrAccessor.get
            ? getterOrAccessor.cache !== false || cache !== false
              ? makeComputed(target, getterOrAccessor.get)
              : getterOrAccessor.get.bind(this)
            : noop
    setter = getterOrAccessor.set ? getterOrAccessor.set.bind(this) : noop
  }
  defineAccessor(target, name, getter, setter)
}

/**
 * Watch property
 *
 * @param {Object} target
 * @param {String|Function} expressionOrFunction
 * @param {Function} callback
 * @param {Object} [options]
 *                 - {Boolean} deep
 *                 - {Boolean} sync
 *                 - {Boolean} lazy
 * @return {Watcher}
 */

function watch (target, expressionOrFunction, callback, options = observe) {
  ensure(target)
  return doWatch(target, expressionOrFunction, callback, options)
}

/**
 * @param {Object} target
 */

function init (target) {
  defineValue(target, WATCHERS_PROPERTY_NAME, [], false)
  defineValue(target, DATA_PROPTERTY_NAME, Object.create(null), false)
  doObserve(target[DATA_PROPTERTY_NAME])
  reactSelfProperties(target)
}

function ensure (target) {
  if (!Object.prototype.hasOwnProperty.call(target, WATCHERS_PROPERTY_NAME)) {
    init(target)
  }
}

/**
 * @param {Object} target
 * @param {Object} methods
 */

function carryMethods (target, methods) {
  everyEntries(methods, (name, method) => {
    target[name] = method.bind(target)
  })
}

/**
 * @param {Object} target
 * @param {String} key
 * @param {*} value
 */

function reactProperty (target, key, value) {
  target[DATA_PROPTERTY_NAME][key] = value
  defineReactive(target[DATA_PROPTERTY_NAME], key, value)
  proxy(target, key)
}

/**
 * @param {Object} target
 * @param {Object} properties
 */

function reactProperties (target, properties) {
  everyEntries(properties, (key, value) => reactProperty(target, key, value))
}

/**
 * @param {Object} target
 */

function reactSelfProperties (target) {
  everyEntries(target, (key, value) => {
    !isFunction(value) && reactProperty(target, key, value)
  })
}

/**
 * @param {Object} target
 * @param {Object} properties
 */

function computeProperties (target, properties) {
  everyEntries(properties, (key, value) => compute(target, key, value))
}

/**
 * @param {Object} target
 * @param {Object} properties
 */

function watchProperties (target, properties) {
  everyEntries(properties, (expression, functionOrOption) => {
    if (isFunction(functionOrOption)) {
      watch(target, expression, functionOrOption)
    } else {
      watch(target, expression, functionOrOption.watcher, functionOrOption)
    }
  })
}

/**
 * @param {Object} target
 * @param {String} key
 */

function proxy (target, key) {
  function getter () {
    return target[DATA_PROPTERTY_NAME][key]
  }
  function setter (value) {
    target[DATA_PROPTERTY_NAME][key] = value
  }
  defineAccessor(target, key, getter, setter)
}
<|endoftext|>


<commit_before>import '../styles/style.css';

function getJSON(path, callback) {
  const httpRequest = new XMLHttpRequest();
  httpRequest.onload = function () {
    if (httpRequest.status >= 200 && httpRequest.status < 400) {
      const data = JSON.parse(httpRequest.responseText);
      if (callback) { callback(data); }
    }
  };
  httpRequest.open('GET', path, true)
  httpRequest.send()

}

(function (){
  getJSON('data.json', function (data){
    let drivers = data.drivers;
    loopOverData(drivers);
  })
})();

function loopOverData(driversData){
  let template;
  let driversListContainer = document.getElementById('drivers-list');

  for (let i = 0; i < driversData.length; i++){

    template =
    `

      ${driversData[i].ranking}°

Points${driversData[i].points}

      ${driversData[i].nationality}

${driversData[i].surname} ${driversData[i].name}

${driversData[i].team} (${driversData[i].teamPoints})

Last GP${driversData[i].lastRace}°

Victories${driversData[i].wins}

Poles${driversData[i].poles}

Best Position${driversData[i].bestPosition}°

`;

    let newDriver = document.createElement('div');

    newDriver.className = 'driver-row';
    newDriver.innerHTML = template;

    driversListContainer.appendChild(newDriver);
  }
}
<commit_msg>Organize code with MVC pattern<commit_after>import '../styles/style.css';

// Models

function Driver(attributes) {
  this.ranking = attributes.ranking
  this.points = attributes.points
  this.nationality = attributes.nationality
  this.surname = attributes.surname
  this.name = attributes.name
  this.team = attributes.team
  this.teamPoints = attributes.teamPoints
  this.lastRace = attributes.lastRace
  this.wins = attributes.wins
  this.poles = attributes.poles
  this.bestPosition = attributes.bestPosition
  this.bestPositionTimes = attributes.bestPositionTimes
}

// Controllers

function getJSON(path, callback) {
  const httpRequest = new XMLHttpRequest();
  httpRequest.onload = function () {
    if (httpRequest.status >= 200 && httpRequest.status < 400) {
      const data = JSON.parse(httpRequest.responseText);
      if (callback) { callback(data); }
    }
  };
  httpRequest.open('GET', path, true)
  httpRequest.send()
}

function renderDrivers() {
  const driversListContainer = document.getElementById('drivers-list');

  getJSON('data.json', function (data){
    const drivers = data
      .drivers
      .map(attributes => new Driver(attributes));

    const driversRows = document.createDocumentFragment();
    let view;

    drivers.forEach( (driver, i) => {
      view = document.createElement('div');
      view.className = 'driver-row';
      view.id = `driver-${i}`
      view.innerHTML = DriverView(driver, i+1)
      driversListContainer.appendChild(view)
    })
  })
}

renderDrivers()

// Views

function DriverView(driver, i) {
  const view = `

        ${driver.ranking}°

Points${driver.points}

        ${driver.nationality}

${driver.surname} ${driver.name}

${driver.team} (${driver.teamPoints})

Last GP${driver.lastRace}°

Victories${driver.wins}

Poles${driver.poles}

Best Position${driver.bestPosition}°

  `
  return view
}
<|endoftext|>


<commit_before>module.exports = `

    <title>Show Me A Dog</title>

Here is your {{breed}}!

      Another?
      Change breed?

`;
<commit_msg>add about section<commit_after>module.exports = `

    <title>Show Me A Dog</title>

Here is your {{breed}}!

      Another?
      Change breed?

Coded by Matt Holland

Powered by Dog CEO's Dog API and the Standford Dogs Dataset

Source Code

`;
<|endoftext|>


<commit_before>'use strict'

const express = require('express')
const bodyParser = require('body-parser')

function api (provider) {
  const router = express.Router('/')

  router.use(bodyParser.json())
  router.use(bodyParser.urlencoded({ extended: false }))

  let {discover, jwks, register, authorize, token, userinfo} = provider

  router.get('/.well-known/openid-configuration', discover.bind(provider))
  router.get('/jwks', jwks.bind(provider))
  router.post('/register', register.bind(provider))
  router.get('/authorize', authorize.bind(provider))
  router.post('/authorize', authorize.bind(provider))
  router.post('/token', token.bind(provider))
  router.get('/userinfo', userinfo.bind(provider))

  return router
}

module.exports = api
<commit_msg>feat(logout): Add binding for /logout api<commit_after>'use strict'

const express = require('express')
const bodyParser = require('body-parser')

function api (provider) {
  const router = express.Router('/')

  router.use(bodyParser.json())
  router.use(bodyParser.urlencoded({ extended: false }))

  let {discover, jwks, register, authorize, token, userinfo, logout } = provider

  router.get('/.well-known/openid-configuration', discover.bind(provider))
  router.get('/jwks', jwks.bind(provider))
  router.post('/register', register.bind(provider))
  router.get('/authorize', authorize.bind(provider))
  router.post('/authorize', authorize.bind(provider))
  router.post('/token', token.bind(provider))
  router.get('/userinfo', userinfo.bind(provider))
  router.get('/logout', logout.bind(provider))

  return router
}

module.exports = api
<|endoftext|>


<commit_before>
const some = {}

// Integer where the range must be specified
some.int = (min, max) =>
  Math.floor(Math.random() * (max - min + 1)) + min

// A positive value integer (minimum 1) with optional max
some.positiveInt = (max = 100) =>
  some.int(1, max)

// A float between 0 (inclusive) and 1 (exclusive)
some.fractionFloat = () =>
  Math.random()

// A float where the range must be specified
some.float = (minInclusive, maxExclusive) =>
  some.fractionFloat() * (maxExclusive - minInclusive) + minInclusive

// A float between 0 (exclusive) and the given max (exclusive and optional)
some.positiveFloat = (maxExclusive = 100) =>
  some.float(1e-10, maxExclusive)

// true or false
some.bool = () =>
  Math.random() >= 0.5

// A string of upper and lowercase latin characters, length is random if omitted
some.chars = (length = some.int(3, 5)) => {
  const capitalStartCode = 'A'.charCodeAt(0)
  const lowerStartCode = 'a'.charCodeAt(0)
  let result = ''

  while (result.length < length) {
    const startCode = some.bool() ? capitalStartCode : lowerStartCode
    result += String.fromCharCode(startCode + some.int(0, 25))
  }
  return result
}

// An alias for some.chars
some.string = some.chars

some.primitive = () => {
  switch (some.int(0, 2)) {
    case 0:
      return some.bool()
    case 1:
      return some.int(0, 100)
    default:
      return some.string()
  }
}

some.array = (length = 3) => {
  const result = []

  while (result.length < length) {
    result.push(some.primitive())
  }
  return result
}

some.object = (numberOfKeys = 3) => {
  const result = {}

  while (Object.keys(result).length < numberOfKeys) {
    result[some.string()] = some.primitive()
  }
  return result
}

some.nullOrUndefined = () =>
  some.bool() ? null : undefined

some.nonExistantReference = some.nullOrUndefined

some.exception = () => {
  function SomeException() {
  }
  return SomeException
}

some.error = some.exception

some.ipAddress = () =>
  `${some.int(1, 255)}.${some.int(1, 255)}.${some.int(1, 255)}.${some.int(1, 255)}`

let uniqueSeq = 0

some.unique = {}

// An integer guaranteed not to produce the same value twice
some.unique.int = () =>
  ++uniqueSeq

some.unique.string = (prefix = some.chars(3)) => {
  let result = prefix
  if (result.includes(' ')) {
    result += ' '
  }
  return result + some.positiveInt()
}

module.exports = some
<commit_msg>some.one<commit_after>
const some = {}

// Integer where the range must be specified
some.int = (min, max) =>
  Math.floor(Math.random() * (max - min + 1)) + min

// A positive value integer (minimum 1) with optional max
some.positiveInt = (max = 100) =>
  some.int(1, max)

// A float between 0 (inclusive) and 1 (exclusive)
some.fractionFloat = () =>
  Math.random()

// A float where the range must be specified
some.float = (minInclusive, maxExclusive) =>
  some.fractionFloat() * (maxExclusive - minInclusive) + minInclusive

// A float between 0 (exclusive) and the given max (exclusive and optional)
some.positiveFloat = (maxExclusive = 100) =>
  some.float(1e-10, maxExclusive)

// true or false
some.bool = () =>
  Math.random() >= 0.5

// A string of upper and lowercase latin characters, length is random if omitted
some.chars = (length = some.int(3, 5)) => {
  const capitalStartCode = 'A'.charCodeAt(0)
  const lowerStartCode = 'a'.charCodeAt(0)
  let result = ''

  while (result.length < length) {
    const startCode = some.bool() ? capitalStartCode : lowerStartCode
    result += String.fromCharCode(startCode + some.int(0, 25))
  }
  return result
}

// An alias for some.chars
some.string = some.chars

some.primitive = () => {
  switch (some.int(0, 2)) {
    case 0:
      return some.bool()
    case 1:
      return some.int(0, 100)
    default:
      return some.string()
  }
}

some.array = (length = 3) => {
  const result = []

  while (result.length < length) {
    result.push(some.primitive())
  }
  return result
}

some.object = (numberOfKeys = 3) => {
  const result = {}

  while (Object.keys(result).length < numberOfKeys) {
    result[some.string()] = some.primitive()
  }
  return result
}

some.nullOrUndefined = () =>
  some.bool() ? null : undefined

some.nonExistantReference = some.nullOrUndefined

some.exception = () => {
  function SomeException() {
  }
  return SomeException
}

some.error = some.exception

some.ipAddress = () =>
  `${some.int(1, 255)}.${some.int(1, 255)}.${some.int(1, 255)}.${some.int(1, 255)}`

some.one = (object) => {
  const keys = Object.keys(object)
  return object[keys[some.int(0, keys.length - 1)]]
}

let uniqueSeq = 0

some.unique = {}

// An integer guaranteed not to produce the same value twice
some.unique.int = () =>
  ++uniqueSeq

some.unique.string = (prefix = some.chars(3)) => {
  let result = prefix
  if (result.includes(' ')) {
    result += ' '
  }
  return result + some.positiveInt()
}

module.exports = some
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import { Card, CardList, MarkdownCard, TestCard, StatefulCard, Container, HotNotify } from './components'
import namespaceStore from './namespaceStore'
import mount from './mount'
import resolveTests from './utils/resolveTests'

let store = namespaceStore()

const main = (namespaces, history) => {
  return <Container namespaces={namespaces} history={history} />
}

// initialize...
const ReactCards = ({ history }) => (

    { main(store.get(), history) }
    <HotNotify/>

)

// main client entry point
const run = () => mount(ReactCards)

const isStr = x =>
  Object.prototype.toString.call(x) === '[object String]'

const processArgs = args => {
  const [fst] = args
  if (isStr(fst)) {
    const [, content, opts] = args
    return [content, {...opts, doc: fst}]
  } else {
    const [content, opts = {}] = args
    return [content, opts]
  }
}

export default function(namespace = 'default') {
  const cards = []
  let nextId = 1
  store.set(namespace, cards)
  return {
    card(...args) {
      const [content, opts] = processArgs(args)
      const CardImpl = typeof content === 'function' ? StatefulCard : Card
      cards.push(<CardImpl {...opts} key={nextId++}>{content}</CardImpl>)
    },
    list() {
      return cards
    },
    component() {
      return <CardList namespace={namespace}>{cards}</CardList>
    },
    test(...args) {
      const [content, opts] = processArgs(args)
      cards.push(<TestCard {...opts} key={nextId++} testModule={content}/>)
    },
    markdown(text) {
      cards.push(<MarkdownCard key={nextId++}>{text}</MarkdownCard>)
    }
  }
}

export {
  resolveTests,
  run,
}
<commit_msg>Revert removing ReactCards from top level export<commit_after>import React, { Component } from 'react'
import { Card, CardList, MarkdownCard, TestCard, StatefulCard, Container, HotNotify } from './components'
import namespaceStore from './namespaceStore'
import mount from './mount'
import resolveTests from './utils/resolveTests'

let store = namespaceStore()

const main = (namespaces, history) => {
  return <Container namespaces={namespaces} history={history} />
}

// initialize...
const ReactCards = ({ history }) => (

    { main(store.get(), history) }
    <HotNotify/>

)

// main client entry point
const run = () => mount(ReactCards)

const isStr = x =>
  Object.prototype.toString.call(x) === '[object String]'

const processArgs = args => {
  const [fst] = args
  if (isStr(fst)) {
    const [, content, opts] = args
    return [content, {...opts, doc: fst}]
  } else {
    const [content, opts = {}] = args
    return [content, opts]
  }
}

export default function(namespace = 'default') {
  const cards = []
  let nextId = 1
  store.set(namespace, cards)
  return {
    card(...args) {
      const [content, opts] = processArgs(args)
      const CardImpl = typeof content === 'function' ? StatefulCard : Card
      cards.push(<CardImpl {...opts} key={nextId++}>{content}</CardImpl>)
    },
    list() {
      return cards
    },
    component() {
      return <CardList namespace={namespace}>{cards}</CardList>
    },
    test(...args) {
      const [content, opts] = processArgs(args)
      cards.push(<TestCard {...opts} key={nextId++} testModule={content}/>)
    },
    markdown(text) {
      cards.push(<MarkdownCard key={nextId++}>{text}</MarkdownCard>)
    }
  }
}

export {
  ReactCards,
  resolveTests,
  run,
}
<|endoftext|>


<commit_before>import Component from './Component';

export default Component;
<commit_msg>Fix: Babel6 does not hack the default behaviour of ES Modules anymore, export 'default' manually<commit_after>'use strict';

// Babel6 does not hack the default behaviour of ES Modules anymore, so we should export
const Component = require('./Component').default;

module.exports = Component;
<|endoftext|>


<commit_before>const moduleName = 'simplifield.dragndrop';

export default angular
  .module(moduleName, [])
  .factory('sfDragNDropService', DragNDropService)
  .directive('sfDrop', ['$parse', 'sfDragNDropService', DropDirective])
  .directive('sfDrag', ['$parse', 'sfDragNDropService', DragDirective])
  .name;

function DragNDropService() {
  const SESSION_KEYS = [
    'item',
    'target',
    'previous',
    'itemIndex',
    'targetIndex',
    'previousIndex',
  ];
  const sfDragNDropService = {
    session: {},
    reset: function reset() {
      Object.keys(sfDragNDropService.session).forEach((key) => {
        if('type' === key) {
          sfDragNDropService.session.type = '';
        } else if (SESSION_KEYS.includes(key)) {
          sfDragNDropService.session[key] = null;
        } else {
          delete sfDragNDropService.session[key];
        }
      });
    }
  };

  sfDragNDropService.reset();

  return sfDragNDropService;
}

function DropDirective($parse, sfDragNDropService) {
  return {
    restrict: 'A',
    link: ($scope, element, attrs) => {
      // Keep a ref to the dragged element
     	const item = $parse(attrs.sfDrop);
      // Setting callbacks
      const onDropCallback = $parse(attrs.sfOnDrop);
      const onDragEnterCallback = $parse(attrs.sfOnDragEnter);
      const onDragLeaveCallback = $parse(attrs.sfOnDragLeave);
      const onDragOverCallback = $parse(attrs.sfOnDragOver);
      // Bind drag events
      element.bind('dragenter', (evt) => {
        if(sfDragNDropService.session.type !== (attrs.sfDragType || 'all')) {
          return;
        }
        evt.preventDefault();
        sfDragNDropService.session.target = item($scope);
        sfDragNDropService.session.targetIndex = onDragEnterCallback($scope, {
          $type: sfDragNDropService.session.type,
          $item: sfDragNDropService.session.item,
          $itemIndex: sfDragNDropService.session.itemIndex,
          $target: sfDragNDropService.session.target,
          $targetIndex: sfDragNDropService.session.targetIndex,
          $session: sfDragNDropService.session
        });
        $scope.$apply();
      });
      element.bind('dragleave', (evt) => {
        if(sfDragNDropService.session.type !== (attrs.sfDragType || 'all')) {
          return;
        }
        evt.preventDefault();
        sfDragNDropService.session.previous = item($scope);
        sfDragNDropService.session.previousIndex = sfDragNDropService.session.targetIndex;
        onDragLeaveCallback($scope, {
          $type: sfDragNDropService.session.type,
          $item: sfDragNDropService.session.item,
          $itemIndex: sfDragNDropService.session.itemIndex,
          $previous: sfDragNDropService.session.previous,
          $previousIndex: sfDragNDropService.session.previousIndex,
          $session: sfDragNDropService.session
        });

        $scope.$apply();
      });
      element.bind('dragover', (evt) => {
        if(sfDragNDropService.session.type !== (attrs.sfDragType || 'all')) {
          return;
        }
        evt.preventDefault();
        sfDragNDropService.session.target = item($scope);
        onDragOverCallback($scope, {
          $type: sfDragNDropService.session.type,
          $item: sfDragNDropService.session.item,
          $itemIndex: sfDragNDropService.session.itemIndex,
          $target: sfDragNDropService.session.target,
          $targetIndex: sfDragNDropService.session.targetIndex,
          $previous: sfDragNDropService.session.target,
          $previousIndex: sfDragNDropService.session.targetIndex,
          $session: sfDragNDropService.session
        });
        $scope.$apply();
      });
      element.bind('drop', (evt) => {
        if(sfDragNDropService.session.type !== (attrs.sfDragType || 'all')) {
          return;
        }
        evt.preventDefault();
        sfDragNDropService.session.target = item($scope);
        onDropCallback($scope, {
          $type: sfDragNDropService.session.type,
          $item: sfDragNDropService.session.item,
          $itemIndex: sfDragNDropService.session.itemIndex,
          $target: sfDragNDropService.session.target,
          $targetIndex: sfDragNDropService.session.targetIndex,
          $previous: sfDragNDropService.session.previous,
          $previousIndex: sfDragNDropService.session.previousIndex,
          $session: sfDragNDropService.session
        });
        $scope.$apply();
      });
    }
  };

}

function DragDirective($parse, sfDragNDropService) {
  return {
    restrict: 'A',
    link: ($scope, element, attrs) => {
      // Keep a ref to the dragged model value
     	const item = $parse(attrs.sfDrag);

      // Try to get dragged datas
     	const getDragData = $parse(attrs.sfDragData);

      // Setting callbacks
      const dragGenerator = attrs.sfDragGenerator ?
        $parse(attrs.sfDragGenerator) :
        null;

      // Setting callbacks
      const onDragCallback = $parse(attrs.sfOnDrag);
      const onDragEndCallback = $parse(attrs.sfOnDragEnd);

      // Make the element draggable
      if(attrs.sfDraggable) {
        $scope.$watch(
          () => {
            return $parse(attrs.sfDraggable)($scope, {
              $type: sfDragNDropService.session.type,
              $item: sfDragNDropService.session.item,
              $itemIndex: sfDragNDropService.session.itemIndex,
              $session: sfDragNDropService.session
            });
          },
          (newVal, oldVal) => {
            attrs.$set('draggable', (!!newVal).toString());
          }
        );
      } else {
        attrs.$set('draggable', 'true');
      }

      // Bind drag events
      element.bind('dragstart', (evt) => {
        var draggedItem = item($scope);
        function computeDragItem() {
           var itemIndex = onDragCallback($scope, {
            $item: draggedItem,
            $session: sfDragNDropService.session
          });
          if(-1 !== itemIndex) {
            sfDragNDropService.session.itemIndex = itemIndex;
            sfDragNDropService.session.item = draggedItem;
            sfDragNDropService.session.type = attrs.sfDragType || 'all';
            sfDragNDropService.session.mime = attrs.sfDragMime || 'text/plain';
            sfDragNDropService.session.data = getDragData($scope) || '' + itemIndex;
            evt.stopPropagation();
            (evt.dataTransfer || evt.originalEvent.dataTransfer)
              .setData(sfDragNDropService.session.mime, sfDragNDropService.session.data);
            (evt.dataTransfer || evt.originalEvent.dataTransfer)
              .effectAllowed = attrs.sfDragEffect || 'move';
          }
        }
        if(dragGenerator) {
          draggedItem = dragGenerator($scope, {
            $type: attrs.sfDragType || 'all',
            $item: draggedItem
          });
        }
        if(draggedItem.then) {
          draggedItem.then((value) => {
            draggedItem = value;
            computeDragItem();
          });
        } else {
          computeDragItem();
        }
        $scope.$apply();
      });

      element.bind('dragend', (evt) => {
        onDragEndCallback($scope, {
          $type: sfDragNDropService.session.type,
          $item: sfDragNDropService.session.item,
          $itemIndex: sfDragNDropService.session.itemIndex,
          $previous: sfDragNDropService.session.previous,
          $previousIndex: sfDragNDropService.session.previousIndex,
          $session: sfDragNDropService.session
        });
        sfDragNDropService.reset();
        $scope.$apply();
      });
    }
  };
}
<commit_msg>fix(es5): cant use fat arrow like this<commit_after>const moduleName = 'simplifield.dragndrop';

export default angular
  .module(moduleName, [])
  .factory('sfDragNDropService', DragNDropService)
  .directive('sfDrop', ['$parse', 'sfDragNDropService', DropDirective])
  .directive('sfDrag', ['$parse', 'sfDragNDropService', DragDirective])
  .name;

function DragNDropService() {
  const SESSION_KEYS = [
    'item',
    'target',
    'previous',
    'itemIndex',
    'targetIndex',
    'previousIndex',
  ];
  const sfDragNDropService = {
    session: {},
    reset: function reset() {
      Object.keys(sfDragNDropService.session).forEach(function(key) {
        if('type' === key) {
          sfDragNDropService.session.type = '';
        } else if (SESSION_KEYS.includes(key)) {
          sfDragNDropService.session[key] = null;
        } else {
          delete sfDragNDropService.session[key];
        }
      });
    }
  };

  sfDragNDropService.reset();

  return sfDragNDropService;
}

function DropDirective($parse, sfDragNDropService) {
  return {
    restrict: 'A',
    link: function($scope, element, attrs) {
      // Keep a ref to the dragged element
     	const item = $parse(attrs.sfDrop);
      // Setting callbacks
      const onDropCallback = $parse(attrs.sfOnDrop);
      const onDragEnterCallback = $parse(attrs.sfOnDragEnter);
      const onDragLeaveCallback = $parse(attrs.sfOnDragLeave);
      const onDragOverCallback = $parse(attrs.sfOnDragOver);
      // Bind drag events
      element.bind('dragenter', function(evt) {
        if(sfDragNDropService.session.type !== (attrs.sfDragType || 'all')) {
          return;
        }
        evt.preventDefault();
        sfDragNDropService.session.target = item($scope);
        sfDragNDropService.session.targetIndex = onDragEnterCallback($scope, {
          $type: sfDragNDropService.session.type,
          $item: sfDragNDropService.session.item,
          $itemIndex: sfDragNDropService.session.itemIndex,
          $target: sfDragNDropService.session.target,
          $targetIndex: sfDragNDropService.session.targetIndex,
          $session: sfDragNDropService.session
        });
        $scope.$apply();
      });
      element.bind('dragleave', function(evt) {
        if(sfDragNDropService.session.type !== (attrs.sfDragType || 'all')) {
          return;
        }
        evt.preventDefault();
        sfDragNDropService.session.previous = item($scope);
        sfDragNDropService.session.previousIndex = sfDragNDropService.session.targetIndex;
        onDragLeaveCallback($scope, {
          $type: sfDragNDropService.session.type,
          $item: sfDragNDropService.session.item,
          $itemIndex: sfDragNDropService.session.itemIndex,
          $previous: sfDragNDropService.session.previous,
          $previousIndex: sfDragNDropService.session.previousIndex,
          $session: sfDragNDropService.session
        });

        $scope.$apply();
      });
      element.bind('dragover', function(evt) {
        if(sfDragNDropService.session.type !== (attrs.sfDragType || 'all')) {
          return;
        }
        evt.preventDefault();
        sfDragNDropService.session.target = item($scope);
        onDragOverCallback($scope, {
          $type: sfDragNDropService.session.type,
          $item: sfDragNDropService.session.item,
          $itemIndex: sfDragNDropService.session.itemIndex,
          $target: sfDragNDropService.session.target,
          $targetIndex: sfDragNDropService.session.targetIndex,
          $previous: sfDragNDropService.session.target,
          $previousIndex: sfDragNDropService.session.targetIndex,
          $session: sfDragNDropService.session
        });
        $scope.$apply();
      });
      element.bind('drop', function(evt) {
        if(sfDragNDropService.session.type !== (attrs.sfDragType || 'all')) {
          return;
        }
        evt.preventDefault();
        sfDragNDropService.session.target = item($scope);
        onDropCallback($scope, {
          $type: sfDragNDropService.session.type,
          $item: sfDragNDropService.session.item,
          $itemIndex: sfDragNDropService.session.itemIndex,
          $target: sfDragNDropService.session.target,
          $targetIndex: sfDragNDropService.session.targetIndex,
          $previous: sfDragNDropService.session.previous,
          $previousIndex: sfDragNDropService.session.previousIndex,
          $session: sfDragNDropService.session
        });
        $scope.$apply();
      });
    }
  };

}

function DragDirective($parse, sfDragNDropService) {
  return {
    restrict: 'A',
    link: function($scope, element, attrs) {
      // Keep a ref to the dragged model value
     	const item = $parse(attrs.sfDrag);

      // Try to get dragged datas
     	const getDragData = $parse(attrs.sfDragData);

      // Setting callbacks
      const dragGenerator = attrs.sfDragGenerator ?
        $parse(attrs.sfDragGenerator) :
        null;

      // Setting callbacks
      const onDragCallback = $parse(attrs.sfOnDrag);
      const onDragEndCallback = $parse(attrs.sfOnDragEnd);

      // Make the element draggable
      if(attrs.sfDraggable) {
        $scope.$watch(
          function() {
            return $parse(attrs.sfDraggable)($scope, {
              $type: sfDragNDropService.session.type,
              $item: sfDragNDropService.session.item,
              $itemIndex: sfDragNDropService.session.itemIndex,
              $session: sfDragNDropService.session
            });
          },
          function(newVal, oldVal) {
            attrs.$set('draggable', (!!newVal).toString());
          }
        );
      } else {
        attrs.$set('draggable', 'true');
      }

      // Bind drag events
      element.bind('dragstart', function(evt) {
        var draggedItem = item($scope);
        function computeDragItem() {
           var itemIndex = onDragCallback($scope, {
            $item: draggedItem,
            $session: sfDragNDropService.session
          });
          if(-1 !== itemIndex) {
            sfDragNDropService.session.itemIndex = itemIndex;
            sfDragNDropService.session.item = draggedItem;
            sfDragNDropService.session.type = attrs.sfDragType || 'all';
            sfDragNDropService.session.mime = attrs.sfDragMime || 'text/plain';
            sfDragNDropService.session.data = getDragData($scope) || '' + itemIndex;
            evt.stopPropagation();
            (evt.dataTransfer || evt.originalEvent.dataTransfer)
              .setData(sfDragNDropService.session.mime, sfDragNDropService.session.data);
            (evt.dataTransfer || evt.originalEvent.dataTransfer)
              .effectAllowed = attrs.sfDragEffect || 'move';
          }
        }
        if(dragGenerator) {
          draggedItem = dragGenerator($scope, {
            $type: attrs.sfDragType || 'all',
            $item: draggedItem
          });
        }
        if(draggedItem.then) {
          draggedItem.then(function(value) {
            draggedItem = value;
            computeDragItem();
          });
        } else {
          computeDragItem();
        }
        $scope.$apply();
      });

      element.bind('dragend', function(evt) {
        onDragEndCallback($scope, {
          $type: sfDragNDropService.session.type,
          $item: sfDragNDropService.session.item,
          $itemIndex: sfDragNDropService.session.itemIndex,
          $previous: sfDragNDropService.session.previous,
          $previousIndex: sfDragNDropService.session.previousIndex,
          $session: sfDragNDropService.session
        });
        sfDragNDropService.reset();
        $scope.$apply();
      });
    }
  };
}
<|endoftext|>


<commit_before>/* global describe, it, beforeEach, afterEach, setTimeout, __dirname */
const expect = require('unexpected')
  .clone()
  .use(require('unexpected-stream'))
  .use(require('unexpected-sinon'));
const sinon = require('sinon');
const PngQuant = require('../lib/PngQuant');
const pathModule = require('path');
const fs = require('fs');
const semver = require('semver');

it.skipIf = function(condition) {
  (condition ? it.skip : it).apply(
    it,
    Array.prototype.slice.call(arguments, 1)
  );
};

describe('PngQuant', () => {
  it('should produce a smaller file with lower quality and ordered dithering', () =>
    expect(
      fs.createReadStream(
        pathModule.resolve(__dirname, 'purplealpha24bit.png')
      ),
      'when piped through',
      new PngQuant([128, '--quality', '60-80', '--nofs']),
      'to yield output satisfying',
      expect.it(resultPngBuffer => {
        expect(resultPngBuffer.length, 'to be within', 0, 8285);
      })
    ));

  it.skipIf(
    semver.satisfies(process.version.replace(/^v/, ''), '>=0.12.0'),
    'should not emit data events while paused',
    done => {
      const pngQuant = new PngQuant();

      function fail() {
        done(new Error('PngQuant emitted data while it was paused!'));
      }
      pngQuant.pause();
      pngQuant.on('data', fail).on('error', done);

      fs.createReadStream(
        pathModule.resolve(__dirname, 'purplealpha24bit.png')
      ).pipe(pngQuant);

      setTimeout(() => {
        pngQuant.removeListener('data', fail);
        const chunks = [];

        pngQuant
          .on('data', chunk => {
            chunks.push(chunk);
          })
          .on('end', () => {
            const resultPngBuffer = Buffer.concat(chunks);
            expect(resultPngBuffer.length, 'to be within', 0, 8285);
            done();
          });

        pngQuant.resume();
      }, 1000);
    }
  );

  it('should emit an error if an invalid image is processed', done => {
    const pngQuant = new PngQuant();

    pngQuant
      .on('error', err => {
        done();
      })
      .on('data', chunk => {
        done(new Error('PngQuant emitted data when an error was expected'));
      })
      .on('end', chunk => {
        done(new Error('PngQuant emitted end when an error was expected'));
      });

    pngQuant.end(Buffer.from('qwvopeqwovkqvwiejvq', 'utf-8'));
  });

  it('should emit a single error if an invalid command line is specified', done => {
    const pngQuant = new PngQuant(['--blabla']);

    let seenError = false;

    pngQuant
      .on('error', err => {
        expect(pngQuant.commandLine, 'to match', /pngquant --blabla/);
        if (seenError) {
          done(new Error('More than one error event was emitted'));
        } else {
          seenError = true;
          setTimeout(done, 100);
        }
      })
      .on('data', chunk => {
        done(new Error('PngQuant emitted data when an error was expected'));
      })
      .on('end', chunk => {
        done(new Error('PngQuant emitted end when an error was expected'));
      });

    pngQuant.end(Buffer.from('qwvopeqwovkqvwiejvq', 'utf-8'));
  });

  describe('#destroy', () => {
    it('should kill the underlying child process', () => {
      const pngQuant = new PngQuant(['-grayscale']);

      return expect.promise(run => {
        pngQuant.write('JFIF');
        setTimeout(
          run(function waitForPngQuantProcess() {
            const pngQuantProcess = pngQuant.pngQuantProcess;
            if (pngQuant.pngQuantProcess) {
              sinon.spy(pngQuantProcess, 'kill');
              pngQuant.destroy();
              sinon.spy(pngQuant, 'emit');
              expect(pngQuantProcess.kill, 'to have calls satisfying', () => {
                pngQuantProcess.kill();
              });
              expect(pngQuant.pngQuantProcess, 'to be falsy');
              expect(pngQuant.bufferedChunks, 'to be falsy');
              setTimeout(
                run(() => {
                  expect(pngQuant.emit, 'to have calls satisfying', []);
                }),
                10
              );
            } else {
              setTimeout(run(waitForPngQuantProcess), 0);
            }
          }),
          0
        );
      });
    });
  });

  expect.addAssertion('<Stream> to error', (expect, subject) =>
    expect.promise(run => {
      subject.once('error', run(err => err));
    })
  );

  expect.addAssertion(
    '<Stream> to error with <any>',
    (expect, subject, value) => {
      expect.errorMode = 'nested';
      return expect(subject, 'to error').then(err =>
        expect(err, 'to satisfy', value)
      );
    }
  );

  describe('with an overridden #binaryPath', () => {
    const childProcess = require('child_process');
    beforeEach(() => {
      PngQuant.getBinaryPath.purgeAll(); // Make sure we don't get a cached value from one of the other tests
      PngQuant.binaryPath = '/foo/bar';
      sinon.spy(childProcess, 'spawn');
    });
    afterEach(() => {
      PngQuant.binaryPath = null;
      childProcess.spawn.restore();
    });

    it('should try launching that binary instead of the one found on the system', () =>
      expect(
        fs.createReadStream(
          pathModule.resolve(__dirname, 'purplealpha24bit.png')
        ),
        'when piped through',
        new PngQuant([128]),
        'to error with',
        /\/foo\/bar ENOENT|write EPIPE/
      ));
  });
});
<commit_msg>Fix lint<commit_after>/* global describe, it, beforeEach, afterEach, setTimeout, __dirname */
const expect = require('unexpected')
  .clone()
  .use(require('unexpected-stream'))
  .use(require('unexpected-sinon'));
const sinon = require('sinon');
const PngQuant = require('../lib/PngQuant');
const pathModule = require('path');
const fs = require('fs');
const semver = require('semver');

it.skipIf = function(condition) {
  (condition ? it.skip : it).apply(
    it,
    Array.prototype.slice.call(arguments, 1)
  );
};

describe('PngQuant', () => {
  it('should produce a smaller file with lower quality and ordered dithering', () =>
    expect(
      fs.createReadStream(
        pathModule.resolve(__dirname, 'purplealpha24bit.png')
      ),
      'when piped through',
      new PngQuant([128, '--quality', '60-80', '--nofs']),
      'to yield output satisfying',
      expect.it(resultPngBuffer => {
        expect(resultPngBuffer.length, 'to be within', 0, 8285);
      })
    ));

  it.skipIf(
    semver.satisfies(process.version.replace(/^v/, ''), '>=0.12.0'),
    'should not emit data events while paused',
    done => {
      const pngQuant = new PngQuant();

      function fail() {
        done(new Error('PngQuant emitted data while it was paused!'));
      }
      pngQuant.pause();
      pngQuant.on('data', fail).on('error', done);

      fs.createReadStream(
        pathModule.resolve(__dirname, 'purplealpha24bit.png')
      ).pipe(pngQuant);

      setTimeout(() => {
        pngQuant.removeListener('data', fail);
        const chunks = [];

        pngQuant
          .on('data', chunk => {
            chunks.push(chunk);
          })
          .on('end', () => {
            const resultPngBuffer = Buffer.concat(chunks);
            expect(resultPngBuffer.length, 'to be within', 0, 8285);
            done();
          });

        pngQuant.resume();
      }, 1000);
    }
  );

  it('should emit an error if an invalid image is processed', done => {
    const pngQuant = new PngQuant();

    pngQuant
      .on('error', () => {
        done();
      })
      .on('data', chunk => {
        done(new Error('PngQuant emitted data when an error was expected'));
      })
      .on('end', chunk => {
        done(new Error('PngQuant emitted end when an error was expected'));
      });

    pngQuant.end(Buffer.from('qwvopeqwovkqvwiejvq', 'utf-8'));
  });

  it('should emit a single error if an invalid command line is specified', done => {
    const pngQuant = new PngQuant(['--blabla']);

    let seenError = false;

    pngQuant
      .on('error', () => {
        expect(pngQuant.commandLine, 'to match', /pngquant --blabla/);
        if (seenError) {
          done(new Error('More than one error event was emitted'));
        } else {
          seenError = true;
          setTimeout(done, 100);
        }
      })
      .on('data', chunk => {
        done(new Error('PngQuant emitted data when an error was expected'));
      })
      .on('end', chunk => {
        done(new Error('PngQuant emitted end when an error was expected'));
      });

    pngQuant.end(Buffer.from('qwvopeqwovkqvwiejvq', 'utf-8'));
  });

  describe('#destroy', () => {
    it('should kill the underlying child process', () => {
      const pngQuant = new PngQuant(['-grayscale']);

      return expect.promise(run => {
        pngQuant.write('JFIF');
        setTimeout(
          run(function waitForPngQuantProcess() {
            const pngQuantProcess = pngQuant.pngQuantProcess;
            if (pngQuant.pngQuantProcess) {
              sinon.spy(pngQuantProcess, 'kill');
              pngQuant.destroy();
              sinon.spy(pngQuant, 'emit');
              expect(pngQuantProcess.kill, 'to have calls satisfying', () => {
                pngQuantProcess.kill();
              });
              expect(pngQuant.pngQuantProcess, 'to be falsy');
              expect(pngQuant.bufferedChunks, 'to be falsy');
              setTimeout(
                run(() => {
                  expect(pngQuant.emit, 'to have calls satisfying', []);
                }),
                10
              );
            } else {
              setTimeout(run(waitForPngQuantProcess), 0);
            }
          }),
          0
        );
      });
    });
  });

  expect.addAssertion('<Stream> to error', (expect, subject) =>
    expect.promise(run => {
      subject.once('error', run(err => err));
    })
  );

  expect.addAssertion(
    '<Stream> to error with <any>',
    (expect, subject, value) => {
      expect.errorMode = 'nested';
      return expect(subject, 'to error').then(err =>
        expect(err, 'to satisfy', value)
      );
    }
  );

  describe('with an overridden #binaryPath', () => {
    const childProcess = require('child_process');
    beforeEach(() => {
      PngQuant.getBinaryPath.purgeAll(); // Make sure we don't get a cached value from one of the other tests
      PngQuant.binaryPath = '/foo/bar';
      sinon.spy(childProcess, 'spawn');
    });
    afterEach(() => {
      PngQuant.binaryPath = null;
      childProcess.spawn.restore();
    });

    it('should try launching that binary instead of the one found on the system', () =>
      expect(
        fs.createReadStream(
          pathModule.resolve(__dirname, 'purplealpha24bit.png')
        ),
        'when piped through',
        new PngQuant([128]),
        'to error with',
        /\/foo\/bar ENOENT|write EPIPE/
      ));
  });
});
<|endoftext|>


<commit_before>/**
 * SEO Checker
 * Copyright (c) 2014 Clever Labs / MIT Licensed (See License)
 * A library to do some basic SEO checks.
 */

// Set up requires
var cheerio = require('cheerio'),
    request = require('request'),
    util    = require('util'),
    Q       = require('q');

module.exports = {
  // Make request and return response body
  load: function(url, callback) {
    // Check if user input protocol
    if (url.indexOf('http://') < 0 && url.indexOf('https://') < 0) {
      url = 'http://' + url;
    }

    console.log('URL ' + url);

    request.get(url, function(error, response, body) {
      if (!error && response.statusCode === 200) {
        return callback(body);
      }

      return callback(false);
    });
  },
  // Parse out the meta data
  meta: function(body) {
    var $     = cheerio.load(body),
        page  = {};

    page.title = $('title').text();
    page.description = $('meta[name=description]').attr('content') || null;
    page.author = $('meta[name=author]').attr('content') || null;
    page.keywords = $('meta[name=keywords]').attr('content') || null;

    var h1s = 0;
    $('h1').each(function() {
      h1s++;
    });
    page.heading1 = $('body h1:first-child').text();
    page.totalHeadings = h1s;
    console.log(util.inspect(page));
    return page;
  }
};

<commit_msg>Add multi-page crawler functionality to seo-checker.<commit_after>/**
 * SEO Checker
 * Copyright (c) 2014 Clever Labs / MIT Licensed (See License)
 * A library to do some basic SEO checks.
 */

// Set up requires
var cheerio = require('cheerio'),
    request = require('request'),
    util    = require('util'), // TODO: Remove in production
    Crawler = require('simplecrawler');

module.exports = {
  // Make request and return response body
  load: function(url, callback) {
    // Check if user input protocol
    if (url.indexOf('http://') < 0 && url.indexOf('https://') < 0) { // TODO: Turn this into its own function
      url = 'http://' + url;
    }

    // Make request and fire callback
    request.get(url, function(error, response, body) {
      if (!error && response.statusCode === 200) {
        return callback(body);
      }

      return callback(false);
    });
  },
  // Parse out the meta data
  meta: function(body) {
    var $     = cheerio.load(body),
        page  = {};

    // Meta signals
    page.title = $('title').text();
    page.description = $('meta[name=description]').attr('content') || null;
    page.author = $('meta[name=author]').attr('content') || null;
    page.keywords = $('meta[name=keywords]').attr('content') || null;

    // Heading signals
    var h1s = 0;
    $('h1').each(function() {
      h1s++;
    });
    page.heading1 = $('body h1:first-child').text().trim().replace('\n', '');
    page.totalHeadings = h1s;

    // Accessibility signals
    var totalImgs       = 0,
        accessibleImgs  = 0;
    $('img').each(function(index) {
      totalImgs++;
      if ($(this).attr('alt') || $(this).attr('title')) {
        accessibleImgs++;
      }
    });
    page.imgAccessibility = (accessibleImgs / totalImgs) * 100;
    //console.log(util.inspect(page)); // TODO: Remove console.log calls
    return page;
  },
  // Crawl multiple pages of a website
  crawl: function(url, options, callback) {
    var crawler       = Crawler.crawl(url),
        opts          = options || {},
        maxPages      = opts.maxPages || 10,
        parsedPages   = [],         // Store parsed pages in this array
        seoParser     = this.meta,  // Reference to `meta` method to call during crawl
        crawlResults  = [];         // Store results in this array and then return it to caller

    // Crawler settings
    crawler.interval            = opts.interval || 250;         // Time between spooling up new requests
    crawler.maxDepth            = opts.depth || 2;              // Maximum deptch of crawl
    crawler.maxConcurrency      = opts.concurrency || 2;        // Number of processes to spawn at a time
    crawler.timeout             = opts.timeout || 1000;         // Milliseconds to wait for server to send headers
    crawler.downloadUnsupported = opts.unsupported || false;    // Save resources by only downloading files Simple Crawler can parse
                                                                // The user agent string to provide - Be cool and don't trick people
    crawler.userAgent           = opts.useragent || 'SEO Checker v1 (https://github.com/Clever-Labs/seo-checker)';

    // Only fetch HTML! You should always set this option unless you have a good reason not to
    if (opts.htmlOnly === true) { // Being explicit about truthy values
      var htmlCondition = crawler.addFetchCondition(function(parsedURL) {
        return !parsedURL.path.match(/\.jpg|jpeg|png|gif|js|txt|css|pdf$/i);
      });
    }

    crawler.on('fetchcomplete', function(queueItem, responseBuffer, response) {
      if (queueItem.stateData.code === 200) {
        crawlResults.push({ url: queueItem.url, body: responseBuffer.toString() });
      }
      if (crawlResults.length >= maxPages) {
        this.stop(); // Stop the crawler
        crawlResults.forEach(function(page, index, results) {
          parsedPages.push(seoParser(page.body));
        });
        if (!callback) {
          return parsedPages;
        } else {
          callback(parsedPages);
        }
      }
    });
  }
};

<|endoftext|>


<commit_before>import R from 'ramda';
import _ from 'lodash';

import required from './validators/required';
import email from './validators/email';
import numeric from './validators/numeric';
import image from './validators/image';
import alpha from './validators/alpha';
import alphanumeric from './validators/alphanumeric';
import date from './validators/date';
import url from './validators/url';
import ip from './validators/ip';
import fqdn from './validators/fqdn';
import string from './validators/string';
import nonBlank from './validators/non-blank';
import length from './validators/length';
import maxLength from './validators/max-length';
import minLength from './validators/min-length';
import minValue from './validators/min-value';
import maxValue from './validators/max-value';
import memberOf from './validators/member-of';
import beginWith from './validators/begin-with';
import regex from './validators/regex';
import notEqual from './validators/not-equal';
import equal from './validators/equal';
import dateFormat from './validators/date-format';
import dateAfter from './validators/date-after';
import dateBefore from './validators/date-before';
import creditCard from './validators/credit-card';
import requiredIf from './validators/required-if';
import taxId from './validators/tax-id';
import phoneNumber from './validators/phone-number';
import mobilePhoneNumber from './validators/mobile-phone-number';
import mongoId from './validators/mongo-id';
import minimumAge from './validators/minimum-age';
import fileType from './validators/file-type';
import boolean from './validators/boolean';

let validation = {
  required: required.validate,
  numeric: numeric.validate,
  email: email.validate,
  image: image.validate,
  alpha: alpha.validate,
  alphanumeric: alphanumeric.validate,
  date: date.validate,
  url: url.validate,
  ip: ip.validate,
  fqdn: fqdn.validate,
  string: string.validate,
  nonBlank: nonBlank.validate,
  creditCard: creditCard.validate,
  mongoId: mongoId.validate,
  phoneNumber: phoneNumber.validate,
  mobilePhoneNumber: mobilePhoneNumber.validate,
  boolean: boolean.validate,
  'fileType:$1': fileType.validate,
  'length:$1': length.validate,
  'maxLength:$1': maxLength.validate,
  'minLength:$1': minLength.validate,
  'maxValue:$1': maxValue.validate,
  'minValue:$1': minValue.validate,
  'memberOf:$1': memberOf.validate,
  'beginWith:$1': beginWith.validate,
  'regex:$1:$2': regex.validate,
  'not-equal:$1': notEqual.validate,
  'equal:$1': equal.validate,
  'dateFormat:$1': dateFormat.validate,
  'dateAfter:$1:$2:$3:$4': dateAfter.validate,
  'dateBefore:$1:$2:$3:$4': dateBefore.validate,
  'requiredIf:$1:$2': requiredIf.validate,
  'taxId:$1': taxId.validate,
  'minimumAge:$1:$2': minimumAge.validate
};

let validationMessages = {
  required: required.message,
  numeric: numeric.message,
  email: email.message,
  image: image.message,
  alpha: alpha.message,
  alphanumeric: alphanumeric.message,
  date: date.message,
  url: url.message,
  ip: ip.message,
  fqdn: fqdn.message,
  string: string.message,
  nonBlank: nonBlank.message,
  creditCard: creditCard.message,
  mongoId: mongoId.message,
  phoneNumber: phoneNumber.message,
  mobilePhoneNumber: mobilePhoneNumber.message,
  boolean: boolean.message,
  'fileType:$1': fileType.message,
  'length:$1': length.message,
  'maxValue:$1': maxValue.message,
  'minValue:$1': minValue.message,
  'maxLength:$1': maxLength.message,
  'minLength:$1': minLength.message,
  'memberOf:$1': memberOf.message,
  'beginWith:$1': beginWith.message,
  'regex:$1:$2': regex.message,
  'not-equal:$1': notEqual.message,
  'equal:$1': equal.message,
  'dateFormat:$1': dateFormat.message,
  'dateAfter:$1:$2:$3:$4': dateAfter.message,
  'dateBefore:$1:$2:$3:$4': dateBefore.message,
  'requiredIf:$1:$2': requiredIf.message,
  'taxId:$1': taxId.message,
  'minimumAge:$1:$2': minimumAge.message
};

class ValidationMessage {
  constructor() {
    this.messageArray = [];
  }
}

/**
 * Create a new validator. When it's created, it will have a deep cloned global
 * validation rules and global validation messages. Any changes made to the
 * instance's rules or messages will not affect the global validation rules
 * and messages.
 * @constructor
 */
class Validator {
  constructor() {
    this.validation = {
      rules: R.clone(validation),
      messages: R.clone(validationMessages)
    };
  }

  /**
   * Create a rule object based on the given rule.
   * @param rule {Object|String}
   * @returns {{name: String, fullName: String, params: Array<String>}}
   */
  _createRuleObject(rule) {
    let ruleObj = {};

    if (R.is(String, rule)) {
      // First variant, everything is embedded as string
      const splitted = rule.split(':');

      // Get only the first part of full rule e.g if range:1:3 then
      // we will get 'range'
      ruleObj.name = R.head(splitted);
      // Get the rule params if e.g range:1:3 -> [1, 3]
      ruleObj.params = splitted.slice(1);
    } else {
      // Second variant, it is already parsed (Object)
      ruleObj.name = rule.name;
      ruleObj.fullName = rule.fullName;
      ruleObj.params = rule.params || [];
    }

    if (!ruleObj.fullName) {
      // Property fullName is the generic full name of validation rule
      // e.g range:1:3 -> range:$1:$2, required -> required
      ruleObj.fullName = ruleObj.params.reduce((ruleName, val, index) => {
        return ruleName + ':$' + (index + 1).toString();
      }, ruleObj.name);
    }

    return ruleObj;
  }

  /**
   * @example
   *   const ruleMapping = {name: ['required']};
   *   const inputObj = {name: ''};
   *   const validator = satpam.create();
   *   const result = validator.validate(ruleMapping, inputObj);
   *
   * @param ruleMapping - An mapping of input property to the available rules
   *   e.g. {name: ['required', 'alpha']}
   * @param inputObj - Input object to be validated
   * @returns {{result: Boolean, messages: Object}}
   */
  validate(ruleMapping, inputObj) {
    const validator = this;
    let result = true;
    let messageObj = new ValidationMessage();

    // Loop through the given rule mapping
    R.keys(ruleMapping).forEach(propertyName => {
      const ruleArray = ruleMapping[propertyName];
      const val = inputObj[propertyName];
      const setValidationMessage = (ruleName, message) => {
        // Set messageObj initial value
        messageObj[propertyName] = messageObj[propertyName] || {};
        messageObj[propertyName][ruleName] = message;
        messageObj.messageArray.push(message);
      };

      const _validate = rule => {
        const ruleObj = this._createRuleObject(rule);
        const validate = validator.validation.rules[ruleObj.fullName];

        if (!R.is(Function, validate)) {
          const ruleObjString = JSON.stringify(ruleObj);
          throw new Error(`${ruleObj.fullName} is not a valid satpam validation rule. Rule object: ${ruleObjString}`);
        }

        const validationResult = validate(val, ruleObj, propertyName, inputObj);

        if (!validationResult) {
          return {
            success: false,
            ruleName: ruleObj.fullName,
            message: validator.getValidationMessage(ruleObj, propertyName, val)
          }
        }

        return {
          success: true,
          ruleName: ruleObj.fullName,
          message: ''
        };
      };

      // Rule array should be something like ['required', 'email']
      ruleArray.forEach(rule => {
        // We will validate and return true if any of the rule passes
        if (R.is(Array, rule)) {
          const resultObjects = rule.map(_validate);
          const overallResult = R.any(R.prop('success'), resultObjects);

          // If none of the results is true then it
          if (!overallResult) {
            result = false;
            resultObjects.forEach(resultObj => {
              setValidationMessage(resultObj.ruleName, resultObj.message);
            });
          }
        } else {
          const resultObj = _validate(rule);

          if (!resultObj.success) {
            result = false;
            setValidationMessage(resultObj.ruleName, resultObj.message);
          }
        }
      });
    });

    return {
      success: result,
      messages: messageObj
    };
  }

  /**
   * @param ruleObj
   * @param propertyName
   * @param val
   * @returns {String}
   */
  getValidationMessage(ruleObj, propertyName, val) {
    const message = this.validation.messages[ruleObj.fullName];
    const messageTemplate = R.is(Function, message) ? message(ruleObj, propertyName, val) : message;
    const compiled = _.template(messageTemplate);
    propertyName = _.startCase(propertyName);

    return compiled({
      propertyName: propertyName,
      ruleName: ruleObj.fullName,
      ruleParams: ruleObj.params,
      value: val
    });
  }

  /**
   * Add custom validation the validator instance, it will only affect the
   * validator instance, if you want to add global validation rule then use
   * addCustomValidation method on satpam module.
   *
   * @example
   *   import satpam from 'satpam';
   *   satpam.addCustomValidation(.., ..);
   *
   * @param ruleName
   * @param validationFunction
   */
  addCustomValidation(ruleName, validateFunction) {
    this.validation.rules[ruleName] = validateFunction;
  }

  /**
   * Set validation message for the given ruleName, it will only affect the
   * validator instance(the receiver), if you want to set global validation
   * message then use addCustomValidation method on satpam module.
   *
   * @example
   *   import satpam from 'satpam';
   *   satpam.setValidationMessage(.., ..);
   *
   * @param ruleName
   * @param message
   */
  setValidationMessage(ruleName, message) {
    this.validation.messages[ruleName] = message;
  }
}

/**
 * Create new Validator instance, will have validations and validation messages
 * that is cloned from the global validations and validation messages.
 * @returns Validator - Satpam validator instance
 */
exports.create = () => new Validator();

/**
 * @example
 *   const ruleMapping = {name: ['required']};
 *   const inputObj = {name: ''};
 *   const validator = satpam.create();
 *   const result = validator.validate(ruleMapping, inputObj);
 *
 * @param ruleMapping - An mapping of input property to the available rules
 *   e.g. {name: ['required', 'alpha']}
 * @param inputObj - Input object to be validated
 * @returns {{result: Boolean, messages: Object}}
 */
exports.validate = (ruleMapping, inputObj) => {
  const validator = new Validator();
  return validator.validate(ruleMapping, inputObj);
};

/**
 * Add custom validation the validator instance, it will only affect the
 * validator instance, if you want to add global validation rule then use
 * addCustomValidation method on satpam module.
 *
 * @example
 *   import satpam from 'satpam';
 *   satpam.addCustomValidation(.., ..);
 *
 * @param ruleName
 * @param validationFunction
 */
exports.addCustomValidation = (ruleName, validationFunction) => {
  validation[ruleName] = validationFunction;
};

/**
 * Set validation message for the given ruleName, it will only affect the
 * validator instance(the receiver), if you want to set global validation
 * message then use addCustomValidation method on satpam module.
 *
 * @example
 *   import satpam from 'satpam';
 *   satpam.setValidationMessage(.., ..);
 *
 * @param ruleName
 * @param message
 */
exports.setValidationMessage = (ruleName, message) => {
  validationMessages[ruleName] = message;
};

/**
 * The global validation object that contains all of the validation rules
 * @type {object}
 */
exports.validation = validation;
<commit_msg>Allow to pass nested rule<commit_after>import R from 'ramda';
import _ from 'lodash';

import required from './validators/required';
import email from './validators/email';
import numeric from './validators/numeric';
import image from './validators/image';
import alpha from './validators/alpha';
import alphanumeric from './validators/alphanumeric';
import date from './validators/date';
import url from './validators/url';
import ip from './validators/ip';
import fqdn from './validators/fqdn';
import string from './validators/string';
import nonBlank from './validators/non-blank';
import length from './validators/length';
import maxLength from './validators/max-length';
import minLength from './validators/min-length';
import minValue from './validators/min-value';
import maxValue from './validators/max-value';
import memberOf from './validators/member-of';
import beginWith from './validators/begin-with';
import regex from './validators/regex';
import notEqual from './validators/not-equal';
import equal from './validators/equal';
import dateFormat from './validators/date-format';
import dateAfter from './validators/date-after';
import dateBefore from './validators/date-before';
import creditCard from './validators/credit-card';
import requiredIf from './validators/required-if';
import taxId from './validators/tax-id';
import phoneNumber from './validators/phone-number';
import mobilePhoneNumber from './validators/mobile-phone-number';
import mongoId from './validators/mongo-id';
import minimumAge from './validators/minimum-age';
import fileType from './validators/file-type';
import boolean from './validators/boolean';

let validation = {
  required: required.validate,
  numeric: numeric.validate,
  email: email.validate,
  image: image.validate,
  alpha: alpha.validate,
  alphanumeric: alphanumeric.validate,
  date: date.validate,
  url: url.validate,
  ip: ip.validate,
  fqdn: fqdn.validate,
  string: string.validate,
  nonBlank: nonBlank.validate,
  creditCard: creditCard.validate,
  mongoId: mongoId.validate,
  phoneNumber: phoneNumber.validate,
  mobilePhoneNumber: mobilePhoneNumber.validate,
  boolean: boolean.validate,
  'fileType:$1': fileType.validate,
  'length:$1': length.validate,
  'maxLength:$1': maxLength.validate,
  'minLength:$1': minLength.validate,
  'maxValue:$1': maxValue.validate,
  'minValue:$1': minValue.validate,
  'memberOf:$1': memberOf.validate,
  'beginWith:$1': beginWith.validate,
  'regex:$1:$2': regex.validate,
  'not-equal:$1': notEqual.validate,
  'equal:$1': equal.validate,
  'dateFormat:$1': dateFormat.validate,
  'dateAfter:$1:$2:$3:$4': dateAfter.validate,
  'dateBefore:$1:$2:$3:$4': dateBefore.validate,
  'requiredIf:$1:$2': requiredIf.validate,
  'taxId:$1': taxId.validate,
  'minimumAge:$1:$2': minimumAge.validate
};

let validationMessages = {
  required: required.message,
  numeric: numeric.message,
  email: email.message,
  image: image.message,
  alpha: alpha.message,
  alphanumeric: alphanumeric.message,
  date: date.message,
  url: url.message,
  ip: ip.message,
  fqdn: fqdn.message,
  string: string.message,
  nonBlank: nonBlank.message,
  creditCard: creditCard.message,
  mongoId: mongoId.message,
  phoneNumber: phoneNumber.message,
  mobilePhoneNumber: mobilePhoneNumber.message,
  boolean: boolean.message,
  'fileType:$1': fileType.message,
  'length:$1': length.message,
  'maxValue:$1': maxValue.message,
  'minValue:$1': minValue.message,
  'maxLength:$1': maxLength.message,
  'minLength:$1': minLength.message,
  'memberOf:$1': memberOf.message,
  'beginWith:$1': beginWith.message,
  'regex:$1:$2': regex.message,
  'not-equal:$1': notEqual.message,
  'equal:$1': equal.message,
  'dateFormat:$1': dateFormat.message,
  'dateAfter:$1:$2:$3:$4': dateAfter.message,
  'dateBefore:$1:$2:$3:$4': dateBefore.message,
  'requiredIf:$1:$2': requiredIf.message,
  'taxId:$1': taxId.message,
  'minimumAge:$1:$2': minimumAge.message
};

class ValidationMessage {
  constructor() {
    this.messageArray = [];
  }
}

/**
 * Create a new validator. When it's created, it will have a deep cloned global
 * validation rules and global validation messages. Any changes made to the
 * instance's rules or messages will not affect the global validation rules
 * and messages.
 * @constructor
 */
class Validator {
  constructor() {
    this.validation = {
      rules: R.clone(validation),
      messages: R.clone(validationMessages)
    };
  }

  /**
   * Create a rule object based on the given rule.
   * @param rule {Object|String}
   * @returns {{name: String, fullName: String, params: Array<String>}}
   */
  _createRuleObject(rule) {
    let ruleObj = {};

    if (R.is(String, rule)) {
      // First variant, everything is embedded as string
      const splitted = rule.split(':');

      // Get only the first part of full rule e.g if range:1:3 then
      // we will get 'range'
      ruleObj.name = R.head(splitted);
      // Get the rule params if e.g range:1:3 -> [1, 3]
      ruleObj.params = splitted.slice(1);
    } else {
      // Second variant, it is already parsed (Object)
      ruleObj.name = rule.name;
      ruleObj.fullName = rule.fullName;
      ruleObj.params = rule.params || [];
    }

    if (!ruleObj.fullName) {
      // Property fullName is the generic full name of validation rule
      // e.g range:1:3 -> range:$1:$2, required -> required
      ruleObj.fullName = ruleObj.params.reduce((ruleName, val, index) => {
        return ruleName + ':$' + (index + 1).toString();
      }, ruleObj.name);
    }

    return ruleObj;
  }

  /**
   * @example
   *   const ruleMapping = {name: ['required']};
   *   const inputObj = {name: ''};
   *   const validator = satpam.create();
   *   const result = validator.validate(ruleMapping, inputObj);
   *
   * @param ruleMapping - An mapping of input property to the available rules
   *   e.g. {name: ['required', 'alpha']}
   * @param inputObj - Input object to be validated
   * @returns {{result: Boolean, messages: Object}}
   */
  validate(ruleMapping, inputObj) {
    const validator = this;
    let result = true;
    let messageObj = new ValidationMessage();

    // Loop through the given rule mapping
    R.keys(ruleMapping).forEach(propertyName => {
      const ruleArray = ruleMapping[propertyName];
      const val = inputObj[propertyName];
      const setValidationMessage = (ruleName, message) => {
        // Set messageObj initial value
        messageObj[propertyName] = messageObj[propertyName] || {};
        messageObj[propertyName][ruleName] = message;
        messageObj.messageArray.push(message);
      };

      const _validate = rule => {
        const ruleObj = this._createRuleObject(rule);
        const validate = validator.validation.rules[ruleObj.fullName];

        if (!R.is(Function, validate)) {
          const ruleObjString = JSON.stringify(ruleObj);
          throw new Error(`${ruleObj.fullName} is not a valid satpam validation rule. Rule object: ${ruleObjString}`);
        }

        const validationResult = validate(val, ruleObj, propertyName, inputObj);

        if (!validationResult) {
          return {
            success: false,
            ruleName: ruleObj.fullName,
            message: validator.getValidationMessage(ruleObj, propertyName, val)
          }
        }

        return {
          success: true,
          ruleName: ruleObj.fullName,
          message: ''
        };
      };

      // Nested rule
      if (!_.isArray(ruleArray)) {
        const nestedResult = this.validate(ruleArray, inputObj[propertyName]);
        result = nestedResult.success && result;

        // Merge the result
        messageObj[propertyName] = nestedResult.messages;
      } else {
        // Rule array should be something like ['required', 'email']
        ruleArray.forEach(rule => {
          // We will validate and return true if any of the rule passes
          if (R.is(Array, rule)) {
            const resultObjects = rule.map(_validate);
            const overallResult = R.any(R.prop('success'), resultObjects);

            // If none of the results is true then it
            if (!overallResult) {
              result = false;
              resultObjects.forEach(resultObj => {
                setValidationMessage(resultObj.ruleName, resultObj.message);
              });
            }
          } else {
            const resultObj = _validate(rule);

            if (!resultObj.success) {
              result = false;
              setValidationMessage(resultObj.ruleName, resultObj.message);
            }
          }
        });

      }
    });

    return {
      success: result,
      messages: messageObj
    };
  }

  /**
   * @param ruleObj
   * @param propertyName
   * @param val
   * @returns {String}
   */
  getValidationMessage(ruleObj, propertyName, val) {
    const message = this.validation.messages[ruleObj.fullName];
    const messageTemplate = R.is(Function, message) ? message(ruleObj, propertyName, val) : message;
    const compiled = _.template(messageTemplate);
    propertyName = _.startCase(propertyName);

    return compiled({
      propertyName: propertyName,
      ruleName: ruleObj.fullName,
      ruleParams: ruleObj.params,
      value: val
    });
  }

  /**
   * Add custom validation the validator instance, it will only affect the
   * validator instance, if you want to add global validation rule then use
   * addCustomValidation method on satpam module.
   *
   * @example
   *   import satpam from 'satpam';
   *   satpam.addCustomValidation(.., ..);
   *
   * @param ruleName
   * @param validationFunction
   */
  addCustomValidation(ruleName, validateFunction) {
    this.validation.rules[ruleName] = validateFunction;
  }

  /**
   * Set validation message for the given ruleName, it will only affect the
   * validator instance(the receiver), if you want to set global validation
   * message then use addCustomValidation method on satpam module.
   *
   * @example
   *   import satpam from 'satpam';
   *   satpam.setValidationMessage(.., ..);
   *
   * @param ruleName
   * @param message
   */
  setValidationMessage(ruleName, message) {
    this.validation.messages[ruleName] = message;
  }
}

/**
 * Create new Validator instance, will have validations and validation messages
 * that is cloned from the global validations and validation messages.
 * @returns Validator - Satpam validator instance
 */
exports.create = () => new Validator();

/**
 * @example
 *   const ruleMapping = {name: ['required']};
 *   const inputObj = {name: ''};
 *   const validator = satpam.create();
 *   const result = validator.validate(ruleMapping, inputObj);
 *
 * @param ruleMapping - An mapping of input property to the available rules
 *   e.g. {name: ['required', 'alpha']}
 * @param inputObj - Input object to be validated
 * @returns {{result: Boolean, messages: Object}}
 */
exports.validate = (ruleMapping, inputObj) => {
  const validator = new Validator();
  return validator.validate(ruleMapping, inputObj);
};

/**
 * Add custom validation the validator instance, it will only affect the
 * validator instance, if you want to add global validation rule then use
 * addCustomValidation method on satpam module.
 *
 * @example
 *   import satpam from 'satpam';
 *   satpam.addCustomValidation(.., ..);
 *
 * @param ruleName
 * @param validationFunction
 */
exports.addCustomValidation = (ruleName, validationFunction) => {
  validation[ruleName] = validationFunction;
};

/**
 * Set validation message for the given ruleName, it will only affect the
 * validator instance(the receiver), if you want to set global validation
 * message then use addCustomValidation method on satpam module.
 *
 * @example
 *   import satpam from 'satpam';
 *   satpam.setValidationMessage(.., ..);
 *
 * @param ruleName
 * @param message
 */
exports.setValidationMessage = (ruleName, message) => {
  validationMessages[ruleName] = message;
};

/**
 * The global validation object that contains all of the validation rules
 * @type {object}
 */
exports.validation = validation;
<|endoftext|>


<commit_before>class Promiseful {
  static fulfil(val) {
    if (typeof val === 'function') {
      return val;
    }

    // Is this a Promise
    if (typeof val === 'object'
      && val.then
      && typeof val.then === 'function') {
      return () => val;
    }

    // Anything else, wrap into a promise into a function
    return () => Promise.resolve(val);
  }

  static parallel(funcs) {
    return Promiseful.all(funcs);
  }

  static all(funcs) {
    return Promise.all(funcs.map(a => Promiseful.fulfil(a)).map(a => a()));
  }

  static race(funcs) {
    if (funcs.length < 1) {
      return Promise.resolve(null);
    }
    return Promise.race(funcs.map(a => Promiseful.fulfil(a)).map(a => a()));
  }

  static series(funcs) {
    return new Promise((resolve, reject) => {
      function next(idx, acc) {
        if (idx >= funcs.length) {
          resolve(acc);
          return;
        }

        const p = Promiseful.fulfil(funcs[idx])();
        p.then(
          (val) => {
            acc.push(val);
            next(idx + 1, acc);
          }                     // eslint-disable-line comma-dangle
        )
        .catch(reject);
      }

      next(0, []);
    });
  }
}

export default Promiseful;
module.exports = Promiseful;

/*
console.log(
  Object.getOwnPropertyNames(Promiseful)
  .filter(prop => typeof Promiseful[prop] === "function")
);
*/
<commit_msg>promiseful.parallelLimit<commit_after>function chunk(array, n) {
  if (n <= array.length) {
    return [array];
  }

  const ret = [];
  for (let i = 0; i < array.length; i += n) {
    ret.push(array.slice(i, i + n));
  }

  return ret;
}

function flatten(arrays) {
  return [].concat(...arrays);
}

class Promiseful {
  static fulfil(val) {
    if (typeof val === 'function') {
      return val;
    }

    // Is this a Promise?
    if (typeof val === 'object'
      && val.then
      && typeof val.then === 'function') {
      return () => val;
    }

    // Anything else, wrap into a promise into a function
    return () => Promise.resolve(val);
  }

  static parallel(funcs) {
    return Promiseful.all(funcs);
  }

  static parallelLimit(funcs, limit) {
    if (limit <= funcs.length) {
      return Promiseful.parallel(funcs);
    }

    const funcsList = chunk(funcs, limit)
      .map(c => (() => Promiseful.parallel(c)));

    return Promiseful.series(funcsList)
      .then(flatten);
  }

  static all(funcs) {
    return Promise.all(funcs.map(a => Promiseful.fulfil(a)).map(a => a()));
  }

  static race(funcs) {
    if (funcs.length < 1) {
      return Promise.resolve(null);
    }

    return Promise.race(funcs.map(a => Promiseful.fulfil(a)).map(a => a()));
  }

  static series(funcs) {
    return new Promise((resolve, reject) => {
      function next(idx, acc) {
        if (idx >= funcs.length) {
          resolve(acc);
          return;
        }

        const p = Promiseful.fulfil(funcs[idx])();
        p.then(
          (val) => {
            acc.push(val);
            next(idx + 1, acc);
          }                     // eslint-disable-line comma-dangle
        )
        .catch(reject);
      }

      next(0, []);
    });
  }
}

export default Promiseful;
module.exports = Promiseful;

/*
console.log(
  Object.getOwnPropertyNames(Promiseful)
  .filter(prop => typeof Promiseful[prop] === "function")
);
*/
<|endoftext|>


<commit_before>var Connection = require('../models/Connection');
var User = require('../models/User');

exports.userRegistersConnections = function(test) {
    test.expect(8);
    var conn1 = new Connection({});
    var conn2 = new Connection({});
    var conn3 = new Connection({});
    var user1 = new User("test1");
    var user2 = new User("test2");

    user1.add(conn1);
    user1.add(conn2);
    user1.add(conn3);
    test.equal(user1.connections.count(), 3, "3 connections added");

    user1.add(conn1);
    test.equal(user1.connections.count(), 3, "Conn1 only added once");

    user1.remove(conn1);
    test.equal(user1.connections.count(), 2, "Conn1 removed");
    test.equal(user1.connections.has(conn2.id), true, "Conn1 removed, 2 still there");
    test.equal(user1.connections.has(conn3.id), true, "Conn1 removed, 3 still there");

    user2.add(conn1);
    user2.add(conn2);

    conn1.close();
    test.equal(user1.connections.count(), 2, "closed conn removed");

    conn2.close();
    conn3.close();
    console.log(user1.connections.count());
    test.equal(user1.connections.count(), 0, "all closed conn removed");
    test.equal(user2.connections.count(), 0, "all closed conn removed");

    test.done();
};
<commit_msg>Remove unit tests that were based on previous functionality<commit_after>var Connection = require('../models/Connection');
var User = require('../models/User');

exports.userRegistersConnections = function(test) {
    test.expect(6);
    var conn1 = new Connection({});
    var conn2 = new Connection({});
    var conn3 = new Connection({});
    var user1 = new User("test1");
    var user2 = new User("test2");

    user1.add(conn1);
    user1.add(conn2);
    user1.add(conn3);
    test.equal(user1.connections.count(), 3, "3 connections added");

    user1.add(conn1);
    test.equal(user1.connections.count(), 3, "Conn1 only added once");

    user1.remove(conn1);
    test.equal(user1.connections.count(), 2, "Conn1 removed");
    test.equal(user1.connections.has(conn2.id), true, "Conn1 removed, 2 still there");
    test.equal(user1.connections.has(conn3.id), true, "Conn1 removed, 3 still there");

    user2.add(conn1);
    user2.add(conn2);

    /* user does not listen to CLOSE of connections, needs to be done by usermanager */
    test.done();
};
<|endoftext|>