<commit_before>/* global PIXI */
import 'pixi.js'
import p2 from 'p2'
import { Howl } from 'howler'

const FPS = 60

const SOUNDS = [
  'wilhelm',
  'music'
]

const TEXTURES = [
  'dave_head',
  'dave_hips',
  'dave_left_forearm',
  'dave_left_hand',
  'dave_left_shin',
  'dave_left_upper_arm',
  'dave_left_upper_leg',
  'dave_right_forearm',
  'dave_right_hand',
  'dave_right_shin',
  'dave_right_upper_arm',
  'dave_right_upper_leg',
  'dave_torso',
  'jack_head',
  'jack_hips',
  'jack_left_forearm',
  'jack_left_hand',
  'jack_left_shin',
  'jack_left_upper_arm',
  'jack_left_upper_leg',
  'jack_right_forearm',
  'jack_right_hand',
  'jack_right_shin',
  'jack_right_upper_arm',
  'jack_right_upper_leg',
  'jack_torso',
  'labs',
  'stage'
]

class Game {
  constructor (elementId, data) {
    this.state = 'waiting'
    this.data = data
    this.gametime = 0.0
    this.frequency = 1.0 / FPS
    this.canvas = document.getElementById(elementId)
    this.camera = {
      x: 0,
      y: 0,
      z: 100
    }
  }

  boot () {
    this.state = 'booting'
    this.init()
    this.load()
  }

  run () {
    this.state = 'running'
    this.resize()
    this.spawn()
    this.loop()
  }

  stop () {
    this.state = 'stopping'
    for (var sound of SOUNDS) {
      this.sounds[sound].unload()
    }
    for (var texture of TEXTURES) {
      this.textures[texture].destroy(true)
    }
    this.viewport.destroy()
    this.game.destroy()
  }

  update (dt) {
    this.world.step(dt)
    this.sprite.position.x = this.head.position[0]
    this.sprite.position.y = this.head.position[1]
    this.sprite.rotation = this.head.angle
  }

  play (sound) {
    this.sounds[sound].play()
  }

  init () {
    this.game = new PIXI.Application(800, 800, { view: this.canvas })

    this.viewport = new PIXI.Container()
    this.game.stage.addChild(this.viewport)

    this.world = new p2.World()
  }

  resize () {
    let ratio = this.canvas.scrollWidth / this.canvas.scrollHeight
    this.viewport.position.x = this.game.renderer.width / 2 + this.camera.x
    this.viewport.position.y = this.game.renderer.height / 2 + this.camera.y
    this.viewport.scale.x = this.camera.z
    this.viewport.scale.y = -this.camera.z * ratio
  }

  load () {
    this.sounds = {}
    for (var sound of SOUNDS) {
      this.sounds[sound] = new Howl({
        src: [require(`assets/${sound}.webm`), require(`assets/${sound}.mp3`)]
      })
    }
    this.textures = {}
    for (var texture of TEXTURES) {
      this.textures[texture] = PIXI.Texture.fromImage(require(`assets/${texture}.png`))
    }
  }

  spawn () {
    this.sprite = new PIXI.Sprite(this.textures['dave_head'])
    this.sprite.anchor.x = 0.5
    this.sprite.anchor.y = 0.5
    this.sprite.width = 1
    this.sprite.height = 1
    this.sprite.interactive = true
    this.sprite.on('mousedown', () => { this.play('wilhelm') })
    this.sprite.on('touchstart', () => { this.play('wilhelm') })
    this.viewport.addChild(this.sprite)

    let ground = new p2.Body({ position: [0, -1] })
    ground.addShape(new p2.Plane())
    this.world.addBody(ground)

    this.head = new p2.Body({ mass: 1, position: [0, 2], angularVelocity: 1 })
    this.head.addShape(new p2.Box({ width: 2, height: 1 }))
    this.world.addBody(this.head)

    if (PROD) {
      this.play('music')
    }
  }

  loop (ms = 0.0) {
    if (this.state !== 'running') {
      return
    }
    let dt = ms / 1000 - this.gametime
    if (ms < 2000) {
      this.gametime = ms / 1000
      this.viewport.visible = false
    } else {
      this.viewport.visible = true
      while (dt > this.frequency) {
        dt -= this.frequency
        this.gametime += this.frequency
        this.update(this.frequency)
      }
    }
    this.data.score = this.gametime
    requestAnimationFrame(this.loop.bind(this))
  }
}

export default Game
<commit_msg>good scaling<commit_after>/* global PIXI */
import 'pixi.js'
import p2 from 'p2'
import { Howl } from 'howler'

const FPS = 60

const SOUNDS = [
  'wilhelm',
  'music'
]

const TEXTURES = [
  'dave_head',
  'dave_hips',
  'dave_left_forearm',
  'dave_left_hand',
  'dave_left_shin',
  'dave_left_upper_arm',
  'dave_left_upper_leg',
  'dave_right_forearm',
  'dave_right_hand',
  'dave_right_shin',
  'dave_right_upper_arm',
  'dave_right_upper_leg',
  'dave_torso',
  'jack_head',
  'jack_hips',
  'jack_left_forearm',
  'jack_left_hand',
  'jack_left_shin',
  'jack_left_upper_arm',
  'jack_left_upper_leg',
  'jack_right_forearm',
  'jack_right_hand',
  'jack_right_shin',
  'jack_right_upper_arm',
  'jack_right_upper_leg',
  'jack_torso',
  'labs',
  'stage'
]

class Game {
  constructor (elementId, data) {
    this.state = 'waiting'
    this.data = data
    this.gametime = 0.0
    this.frequency = 1.0 / FPS
    this.canvas = document.getElementById(elementId)
    this.camera = {
      x: 0,
      y: 0,
      z: 100
    }
  }

  boot () {
    this.state = 'booting'
    this.init()
    this.load()
  }

  run () {
    this.state = 'running'
    this.resize()
    this.spawn()
    this.loop()
  }

  stop () {
    this.state = 'stopping'
    for (var sound of SOUNDS) {
      this.sounds[sound].unload()
    }
    for (var texture of TEXTURES) {
      this.textures[texture].destroy(true)
    }
    this.viewport.destroy()
    this.game.destroy()
  }

  update (dt) {
    this.world.step(dt)
    this.sprite.position.x = this.head.position[0]
    this.sprite.position.y = this.head.position[1]
    this.sprite.rotation = this.head.angle
  }

  play (sound) {
    this.sounds[sound].play()
  }

  init () {
    this.game = new PIXI.Application(800, 500, { view: this.canvas })

    this.viewport = new PIXI.Container()
    this.game.stage.addChild(this.viewport)

    this.world = new p2.World()
  }

  resize () {
    this.viewport.position.x = this.game.renderer.width / 2 + this.camera.x
    this.viewport.position.y = this.game.renderer.height / 2 + this.camera.y
    let ratio = this.canvas.scrollWidth / this.canvas.scrollHeight
    this.viewport.scale.x = this.camera.z
    this.viewport.scale.y = -this.camera.z
    if (ratio > 1.6) this.viewport.scale.x /= (ratio / 1.6)
    if (ratio < 1.6) this.viewport.scale.y *= (ratio / 1.6)
  }

  load () {
    this.sounds = {}
    for (var sound of SOUNDS) {
      this.sounds[sound] = new Howl({
        src: [require(`assets/${sound}.webm`), require(`assets/${sound}.mp3`)]
      })
    }
    this.textures = {}
    for (var texture of TEXTURES) {
      this.textures[texture] = PIXI.Texture.fromImage(require(`assets/${texture}.png`))
    }
  }

  spawn () {
    let stage = new PIXI.Sprite(this.textures['stage'])
    stage.anchor.x = 0.5
    stage.anchor.y = 0.5
    stage.scale.x = 0.01
    stage.scale.y = 0.01
    this.viewport.addChild(stage)

    this.sprite = new PIXI.Sprite(this.textures['dave_head'])
    this.sprite.anchor.x = 0.5
    this.sprite.anchor.y = 0.5
    this.sprite.width = 1
    this.sprite.height = 1
    this.sprite.interactive = true
    this.sprite.on('mousedown', () => { this.play('wilhelm') })
    this.sprite.on('touchstart', () => { this.play('wilhelm') })
    this.viewport.addChild(this.sprite)

    let ground = new p2.Body({ position: [0, -2.5] })
    ground.addShape(new p2.Plane())
    this.world.addBody(ground)

    this.head = new p2.Body({ mass: 1, position: [0, 3], angularVelocity: 10 })
    this.head.addShape(new p2.Box({ width: 1, height: 1 }))
    this.world.addBody(this.head)

    if (PROD) {
      this.play('music')
    }
  }

  loop (ms = 0.0) {
    if (this.state !== 'running') {
      return
    }
    let dt = ms / 1000 - this.gametime
    if (ms < 2000) {
      this.gametime = ms / 1000
      this.viewport.visible = false
    } else {
      this.viewport.visible = true
      while (dt > this.frequency) {
        dt -= this.frequency
        this.gametime += this.frequency
        this.update(this.frequency)
      }
    }
    this.data.score = this.gametime
    requestAnimationFrame(this.loop.bind(this))
  }
}

export default Game
<|endoftext|>


<commit_before>var React = require('react/addons');
var PureRenderMixin = React.addons.PureRenderMixin;
var Item = require('./item');

var InfiniteGrid = React.createClass({

    mixins: [ PureRenderMixin ],

    propTypes: {
        entries: React.PropTypes.arrayOf(React.PropTypes.element).isRequired,
        height: React.PropTypes.number,
        width: React.PropTypes.number,
        padding: React.PropTypes.number,
        wrapperHeight: React.PropTypes.number,
    },

    getDefaultProps: function() {
        return {
            padding: 10,
            entries: [],
            height: 250,
            width: 250,
        };
    },

    getInitialState: function() {
        return {
            selectMode: false,
            minHeight: window.innerHeight * 2,
            minItemIndex: 0,
            maxItemIndex: 100,
            itemDimensions: {
                height: this._itemHeight(),
                width: this._itemHeight(),
                gridWidth: 0,
                itemsPerRow: 2,
            },
        };
    },

    // METHODS

    _wrapperStyle: function() {
        return {
            maxHeight: window.innerHeight,
            overflowY: 'scroll',
            width: '100%',
            height: this.props.wrapperHeight,
            WebkitOverflowScrolling: 'touch',
        };
    },

    _gridStyle: function() {
        return {
            position: "relative",
            marginTop: this.props.padding,
            marginLeft: this.props.padding,
            minHeight: this.state.minHeight,
        };
    },

    _getGridRect: function() {
        return this.refs.grid.getDOMNode().getBoundingClientRect();
    },

    _getWrapperRect: function() {
        return this.refs.wrapper.getDOMNode().getBoundingClientRect();
    },

    _visibleIndexes: function() {
        var itemsPerRow = this._itemsPerRow();

        // The number of rows that the user has scrolled past
        var scrolledPast = (this._scrolledPastRows() * itemsPerRow);
        if (scrolledPast < 0) scrolledPast = 0;

        // If i have scrolled past 20 items, but 60 are visible on screen,
        // we do not want to change the minimum
        var min = scrolledPast - itemsPerRow;
        if (min < 0) min = 0;

        // the maximum should be the number of items scrolled past, plus some
        // buffer
        var bufferRows = this._numVisibleRows() + 1;
        var max = scrolledPast + (itemsPerRow * bufferRows);
        if (max > this.props.entries.length) max = this.props.entries.length;

        this.setState({
            minItemIndex: min,
            maxItemIndex: max,
        });
    },

    _itemsPerRow: function() {
        return Math.floor(this._getGridRect().width / this._itemWidth());
    },

    _totalRows: function() {
        var scrolledPastHeight = (this.props.entries.length / this._itemsPerRow()) * this._itemHeight();
        if (scrolledPastHeight < 0) return 0;
        return scrolledPastHeight;
    },

    _scrolledPastRows: function() {
        var rect = this._getGridRect();
        var topScrollOffset = rect.height - rect.bottom;
        return Math.floor(topScrollOffset / this._itemHeight());
    },

    _itemHeight: function() {
        return this.props.height + (2 * this.props.padding);
    },

    _itemWidth: function() {
        return this.props.width + (2 * this.props.padding);
    },

    _numVisibleRows: function() {
        return Math.ceil(this._getWrapperRect().height / this._itemHeight());
    },

    // LIFECYCLE

    componentWillMount: function() {
        window.addEventListener('resize', this._resizeListener);
    },

    componentDidMount: function() {
        this.setState({
            itemDimensions: {
                height: this._itemHeight(),
                width: this._itemHeight(),
                gridWidth: this._getGridRect().width,
                itemsPerRow: this._itemsPerRow(),
            },
            minHeight: this._totalRows(),
        });
        this._visibleIndexes();
    },

    componentWillUnmount: function() {
        window.removeEventListener('resize', this._resizeListener);
    },

    // LISTENERS

    _scrollListener: function(event) {
        this._visibleIndexes();
    },

    _resizeListener: function(event) {
        if (!this.props.wrapperHeight) {
            this.setState({
                wrapperHeight: window.innerHeight,
            });
        }
        this._visibleIndexes();
    },

    // RENDER

    render: function() {
        var entries = [];
        if (this.props.entries.length > 0) {
            for (var i = this.state.minItemIndex; i <= this.state.maxItemIndex; i++) {
                var entry = this.props.entries[i];
                if (entry) {
                    entries.push(React.createElement(Item, {
                        key: "item-" + i,
                        index: i,
                        padding: this.props.padding,
                        dimensions: this.state.itemDimensions,
                    }, entry));
                }
            }
        }

        return(

                    {entries}

        );
    },
});

module.exports = InfiniteGrid;
<commit_msg>Add support for a lazy loading callback.<commit_after>var React = require('react/addons');
var PureRenderMixin = React.addons.PureRenderMixin;
var Item = require('./item');

var InfiniteGrid = React.createClass({

    mixins: [ PureRenderMixin ],

    propTypes: {
        entries: React.PropTypes.arrayOf(React.PropTypes.element).isRequired,
        height: React.PropTypes.number,
        width: React.PropTypes.number,
        padding: React.PropTypes.number,
        wrapperHeight: React.PropTypes.number,
        lazyCallback: React.PropTypes.func,
    },

    getDefaultProps: function() {
        return {
            padding: 10,
            entries: [],
            height: 250,
            width: 250,
        };
    },

    getInitialState: function() {
        return {
            selectMode: false,
            minHeight: window.innerHeight * 2,
            minItemIndex: 0,
            maxItemIndex: 100,
            itemDimensions: {
                height: this._itemHeight(),
                width: this._itemHeight(),
                gridWidth: 0,
                itemsPerRow: 2,
            },
        };
    },

    // METHODS

    _wrapperStyle: function() {
        return {
            maxHeight: window.innerHeight,
            overflowY: 'scroll',
            width: '100%',
            height: this.props.wrapperHeight,
            WebkitOverflowScrolling: 'touch',
        };
    },

    _gridStyle: function() {
        return {
            position: "relative",
            marginTop: this.props.padding,
            marginLeft: this.props.padding,
            minHeight: this.state.minHeight,
        };
    },

    _getGridRect: function() {
        return this.refs.grid.getDOMNode().getBoundingClientRect();
    },

    _getWrapperRect: function() {
        return this.refs.wrapper.getDOMNode().getBoundingClientRect();
    },

    _visibleIndexes: function() {
        var itemsPerRow = this._itemsPerRow();

        // The number of rows that the user has scrolled past
        var scrolledPast = (this._scrolledPastRows() * itemsPerRow);
        if (scrolledPast < 0) scrolledPast = 0;

        // If i have scrolled past 20 items, but 60 are visible on screen,
        // we do not want to change the minimum
        var min = scrolledPast - itemsPerRow;
        if (min < 0) min = 0;

        // the maximum should be the number of items scrolled past, plus some
        // buffer
        var bufferRows = this._numVisibleRows() + 1;
        var max = scrolledPast + (itemsPerRow * bufferRows);
        if (max > this.props.entries.length) max = this.props.entries.length;

        this.setState({
            minItemIndex: min,
            maxItemIndex: max,
        }, function() {
            this._lazyCallback();
        });
    },

    _itemsPerRow: function() {
        return Math.floor(this._getGridRect().width / this._itemWidth());
    },

    _totalRows: function() {
        var scrolledPastHeight = (this.props.entries.length / this._itemsPerRow()) * this._itemHeight();
        if (scrolledPastHeight < 0) return 0;
        return scrolledPastHeight;
    },

    _scrolledPastRows: function() {
        var rect = this._getGridRect();
        var topScrollOffset = rect.height - rect.bottom;
        return Math.floor(topScrollOffset / this._itemHeight());
    },

    _itemHeight: function() {
        return this.props.height + (2 * this.props.padding);
    },

    _itemWidth: function() {
        return this.props.width + (2 * this.props.padding);
    },

    _numVisibleRows: function() {
        return Math.ceil(this._getWrapperRect().height / this._itemHeight());
    },

    _lazyCallback: function() {
        if ((this.state.maxItemIndex === this.props.entries.length) && this.props.lazyCallback) {
            this.props.lazyCallback();
        }
    },

    // LIFECYCLE

    componentWillMount: function() {
        window.addEventListener('resize', this._resizeListener);
    },

    componentDidMount: function() {
        this.setState({
            itemDimensions: {
                height: this._itemHeight(),
                width: this._itemHeight(),
                gridWidth: this._getGridRect().width,
                itemsPerRow: this._itemsPerRow(),
            },
            minHeight: this._totalRows(),
        });
        this._visibleIndexes();
    },

    componentWillUnmount: function() {
        window.removeEventListener('resize', this._resizeListener);
    },

    // LISTENERS

    _scrollListener: function(event) {
        this._visibleIndexes();
    },

    _resizeListener: function(event) {
        if (!this.props.wrapperHeight) {
            this.setState({
                wrapperHeight: window.innerHeight,
            });
        }
        this._visibleIndexes();
    },

    // RENDER

    render: function() {
        var entries = [];
        if (this.props.entries.length > 0) {
            for (var i = this.state.minItemIndex; i <= this.state.maxItemIndex; i++) {
                var entry = this.props.entries[i];
                if (entry) {
                    entries.push(React.createElement(Item, {
                        key: "item-" + i,
                        index: i,
                        padding: this.props.padding,
                        dimensions: this.state.itemDimensions,
                    }, entry));
                }
            }
        }

        return(

                    {entries}

        );
    },
});

module.exports = InfiniteGrid;
<|endoftext|>


<commit_before>var component = require('omniscient'),
    Immutable = require('immutable'),
    qwery = require('qwery'),
    React = require('react');

var CELL_SIZE = 30,
    BORDER_SIZE = 1;

function position(a) {
    return (Math.floor(a / 3) + 2) * BORDER_SIZE +
        a * (CELL_SIZE + BORDER_SIZE);
}

function gridSize(n) {
    return position(n) + BORDER_SIZE;
}

var Cell = component(function (props) {
    return React.DOM.rect({
        x: position(props.x),
        y: position(props.y),
        width: CELL_SIZE,
        height: CELL_SIZE,
        className: "sudoku__cell"
    });
});

var Grid = component(function () {
    var cells = Immutable.Range(0, 9).flatMap(function (x) {
        return Immutable.Range(0, 9).map(function (y) {
            return Cell(x + "_" + y, {
                x: x,
                y: y
            });
        });
    });

    var background = React.DOM.rect({
        x: 0,
        y: 0,
        width: gridSize(9),
        height: gridSize(9),
        className: "sudoku__background"
    });

    return React.DOM.svg({
        width: gridSize(9),
        height: gridSize(9)
    }, background, cells.toJS());
});

React.render(Grid(), qwery('.js-sudoku')[0]);

<commit_msg>Remove gridSize - same function as position<commit_after>var component = require('omniscient'),
    Immutable = require('immutable'),
    qwery = require('qwery'),
    React = require('react');

var CELL_SIZE = 30,
    BORDER_SIZE = 1;

function position(a) {
    return (Math.floor(a / 3) + 2) * BORDER_SIZE +
        a * (CELL_SIZE + BORDER_SIZE);
}

var Cell = component(function (props) {
    return React.DOM.rect({
        x: position(props.x),
        y: position(props.y),
        width: CELL_SIZE,
        height: CELL_SIZE,
        className: "sudoku__cell"
    });
});

var Grid = component(function () {
    var cells = Immutable.Range(0, 9).flatMap(function (x) {
        return Immutable.Range(0, 9).map(function (y) {
            return Cell(x + "_" + y, {
                x: x,
                y: y
            });
        });
    });

    var background = React.DOM.rect({
        x: 0,
        y: 0,
        width: position(9),
        height: position(9),
        className: "sudoku__background"
    });

    return React.DOM.svg({
        width: position(9),
        height: position(9)
    }, background, cells.toJS());
});

React.render(Grid(), qwery('.js-sudoku')[0]);

<|endoftext|>


<commit_before>var _ = require('lodash'),
    Chance = require('chance'),
    jsonPath = require('jsonpath')

var hazy = {}

hazy.config = {
  global: {
    seed: null
  }
}

hazy.meta = {
  types: {
    basic  : ['bool', 'character', 'integer', 'natural', 'string'],
    text   : ['paragraph', 'sentence', 'syllable', 'word'],
    person : ['age', 'birthday', 'cpf', 'first', 'gender', 'last', 'name', 'prefix', 'ssn', 'suffix'],
    mobile : ['android_id', 'apple_token', 'bb_pin', 'wp7_anid', 'wp8_anid2'],
    web    : ['color', 'domain', 'email', 'fbid', 'google_analytics', 'hashtag', 'ip', 'ipv6', 'klout', 'tld', 'twitter', 'url'],
    geo    : ['address', 'altitude', 'areacode', 'city', 'coordinates', 'country', 'depth', 'geohash', 'latitude', 'longitude', 'phone', 'postal', 'province', 'state', 'street', 'zip'],
    time   : ['ampm', 'date', 'hammertime', 'hour', 'millisecond', 'minute', 'month', 'second', 'timestamp', 'year'],
    misc   : ['guid', 'hash', 'hidden', 'n', 'normal', 'radio', 'rpg', 'tv', 'unique', 'weighted']

    // aliases
    // '?' : 'bool',
    // '#' : 'number',
    // '_' : 'string',
    // '$' : this.finance,
  }
}

hazy.lang = {
  expression: /\|(:|~|@)(.*?)?\|/,

  tokens: {
    "|": function(prev, next) { // expression start/end
      var isPrevToken    = this.validate(prev),
          isNextTokenEnd = /\|/.test(next)

      if (isPrevToken || isNextTokenEnd) {
        throw hazy.lang.exception('Cannot define an empty expression')
      }

      if (!next) {
        // return true
        // TODO - return a special value saying that this is the end of the token expression sequence
      }
    },

    ":": function(prev, next) { // property accessor
      if (!prev) {
        throw 'Syntax error, : requires a left operand'
      }

      return prev[next]
    },

    "~": function(prev, next, rest) { // random data
      var randProp   = next.split(':')[0] // match text to next : or |
          randVal    = next.split(':')[1]
          canUseProp = hazy.random.hasOwnProperty(randProp)

      if (canUseProp) {
        var randObjByProp  = hazy.random[randProp]
            randObjSubType = randVal // get property of random operator following ":"

        if (!randObjByProp || !randObjByProp[randObjSubType]) {
          throw hazy.lang.exception('Invalid random data type "' + randObjSubType + '". Supported:', hazy.meta.types[randProp])
        }

        return randObjByProp[randObjSubType]()
      } else {
        throw hazy.lang.exception('Invalid random data category "' + randProp + '". Supported', hazy.meta.types)
      }
    },

    "@": function(prev, next) { // link to stub
      return hazy.stub.get(next)
    },

    validate: function(token) {
      return this.hasOwnProperty(token)
    },

    process: function(token, prev, next, rest) {
      return _.bindKey(hazy.lang.tokens, token, prev, next, rest)()
    }
  },

  process: function(str) {
    var matches = str.match(this.expression)
    var results = []

    _.forEach(matches, function(match, i) {
      var isToken = hazy.lang.tokens.validate(match)

      if (isToken) {
        var prevMatch   = matches[i - 1],
            nextMatch   = matches[i + 1],
            restMatches = _.drop(matches, i + 1),
            expResult   = this.tokens.process(match, prevMatch, nextMatch, restMatches)

        if (expResult) {
          results.push(expResult)
        }
      }
    }, this)

    results = _.reduce(results, function(total, n) { return total + n })

    // replace tokens in original string with processed replacements
    if (_.isString(results)) {
      return str.replace(this.expression, results)
    }

    return results || str
  },

  exception: function(msg) {
    return '[Hazy syntax error] ' + msg
  }
}

hazy.random = _.mapValues(hazy.meta.types, function(value, key) {
  var hazyRandObj = {}

  _.forEach(value, function(v) {
     hazyRandObj[v] = function() { return new Chance()[v]() }
  })

  return hazyRandObj
})

hazy.stub = {
  pool: {},

  get: function(key) {
    return this.pool[key]
  },

  // FIXME - allow for optional non-lazy override. by defult this should return a function
  register: function(name, stub) {
    this.pool[name] = this.process(stub)
  },

  process: function(stub) { // dynamically process stub values by type (object, string, array, or function)
    var processedStub = {}

    if (_.isPlainObject(stub)) {
      _.mapKeys(stub, function(value, key) {
        var processedKey = hazy.lang.process(key),
            nextStub     = value

        processedStub[processedKey] = this.process(nextStub)
      }, this)
    }

    if (_.isArray(stub)) {
      return _.map(stub, hazy.lang.process)
    }

    if (_.isString(stub)) {
      return hazy.lang.process(stub)
    }

    if (_.isFunction(stub)) {
      return stub(null, hazy.config.global.seed) // TODO - provide/support per-instance seed and the object key
    }

    // TODO - determine if current stub matches a regex or name
    // hazy.stub.

    return processedStub
  },

  load: function(file) { // TODO - load from FS
    if (_.isArray(file)) {
      _.forEach(file, function() {

      })
    } else {

    }
  },

  write: function() {
    // TODO - write to FS
  }
}

////////

//////

hazy.pattern = {
  pool: {},

  appliesTo: function(stub) { // determines if a seed can be populated to the provided function
    return this.pool.hasOwnProperty(stub)
  },

  register: function(path, value) {
    this.pool[path] = value
  },

  registerConfig: function(patternConfig) {
    var stubName       = patternConfig.stub,
        patternPath    = patternConfig.path,
        patternHandler = patternConfig.handler,
        patternKey     = stubName || stubPath

    if (!_.contains(this.pool, stubName)) {
      throw 'Stub is not registered in pool, failed to register pattern ' + stubName
    }

    this.pool[patternKey] = {name: stubName, path: stubPath, handler: patternHandler}
  }
}

hazy.seed   = _.cloneDeep(hazy.pattern)
hazy.filter = _.cloneDeep(hazy.pattern)
<commit_msg>cleanup<commit_after>var _ = require('lodash'),
    Chance = require('chance'),
    jsonPath = require('jsonpath')

var hazy = {}

hazy.config = {
  global: {
    seed: null
  }
}

hazy.meta = {
  types: {
    basic  : ['bool', 'character', 'integer', 'natural', 'string'],
    text   : ['paragraph', 'sentence', 'syllable', 'word'],
    person : ['age', 'birthday', 'cpf', 'first', 'gender', 'last', 'name', 'prefix', 'ssn', 'suffix'],
    mobile : ['android_id', 'apple_token', 'bb_pin', 'wp7_anid', 'wp8_anid2'],
    web    : ['color', 'domain', 'email', 'fbid', 'google_analytics', 'hashtag', 'ip', 'ipv6', 'klout', 'tld', 'twitter', 'url'],
    geo    : ['address', 'altitude', 'areacode', 'city', 'coordinates', 'country', 'depth', 'geohash', 'latitude', 'longitude', 'phone', 'postal', 'province', 'state', 'street', 'zip'],
    time   : ['ampm', 'date', 'hammertime', 'hour', 'millisecond', 'minute', 'month', 'second', 'timestamp', 'year'],
    misc   : ['guid', 'hash', 'hidden', 'n', 'normal', 'radio', 'rpg', 'tv', 'unique', 'weighted']

    // aliases
    // '?' : 'bool',
    // '#' : 'number',
    // '_' : 'string',
    // '$' : this.finance,
  }
}

hazy.lang = {
  expression: /\|(:|~|@)(.*?)?\|/,

  tokens: {
    "|": function(prev, next) { // expression start/end
      var isPrevToken    = this.validate(prev),
          isNextTokenEnd = /\|/.test(next)

      if (isPrevToken || isNextTokenEnd) {
        throw hazy.lang.exception('Cannot define an empty expression')
      }

      if (!next) {
        // return true
        // TODO - return a special value saying that this is the end of the token expression sequence
      }
    },

    ":": function(prev, next) { // property accessor
      if (!prev) {
        throw 'Syntax error, : requires a left operand'
      }

      return prev[next]
    },

    "~": function(prev, next, rest) { // random data
      var randProp   = next.split(':')[0] // match text to next : or |
          randVal    = next.split(':')[1]
          canUseProp = hazy.random.hasOwnProperty(randProp)

      if (canUseProp) {
        var randObjByProp  = hazy.random[randProp]
            randObjSubType = randVal // get property of random operator following ":"

        if (!randObjByProp || !randObjByProp[randObjSubType]) {
          throw hazy.lang.exception('Invalid random data type "' + randObjSubType + '". Supported:', hazy.meta.types[randProp])
        }

        return randObjByProp[randObjSubType]()
      } else {
        throw hazy.lang.exception('Invalid random data category "' + randProp + '". Supported', hazy.meta.types)
      }
    },

    "@": function(prev, next) { // link to stub
      return hazy.stub.get(next)
    },

    validate: function(token) {
      return this.hasOwnProperty(token)
    },

    process: function(token, prev, next, rest) {
      return _.bindKey(hazy.lang.tokens, token, prev, next, rest)()
    }
  },

  process: function(str) {
    var matches = str.match(this.expression)
    var results = []

    _.forEach(matches, function(match, i) {
      var isToken = hazy.lang.tokens.validate(match)

      if (isToken) {
        var prevMatch   = matches[i - 1],
            nextMatch   = matches[i + 1],
            restMatches = _.drop(matches, i + 1),
            expResult   = this.tokens.process(match, prevMatch, nextMatch, restMatches)

        if (expResult) {
          results.push(expResult)
        }
      }
    }, this)

    results = _.reduce(results, function(total, n) { return total + n })

    // replace tokens in original string with processed replacements
    if (_.isString(results)) {
      return str.replace(this.expression, results)
    }

    return results || str
  },

  exception: function(msg) {
    return '[Hazy syntax error] ' + msg
  }
}

hazy.random = _.mapValues(hazy.meta.types, function(value, key) {
  var hazyRandObj = {}

  _.forEach(value, function(v) {
     hazyRandObj[v] = function() { return new Chance()[v]() }
  })

  return hazyRandObj
})

hazy.stub = {
  pool: {},

  get: function(key) {
    return this.pool[key]
  },

  // FIXME - allow for optional non-lazy override. by defult this should return a function
  register: function(name, stub) {
    this.pool[name] = this.process(stub)
  },

  process: function(stub) { // dynamically process stub values by type (object, string, array, or function)
    var processedStub = {}

    if (_.isPlainObject(stub)) {
      _.mapKeys(stub, function(value, key) {
        var processedKey = hazy.lang.process(key),
            nextStub     = value

        processedStub[processedKey] = this.process(nextStub)
      }, this)
    }

    if (_.isArray(stub)) {
      return _.map(stub, hazy.lang.process)
    }

    if (_.isString(stub)) {
      return hazy.lang.process(stub)
    }

    if (_.isFunction(stub)) {
      return stub(null, hazy.config.global.seed) // TODO - provide/support per-instance seed and the object key
    }

    // TODO - determine if current stub matches a regex or name
    // hazy.stub.

    return processedStub
  },

  load: function(file) { // TODO - load from FS
    if (_.isArray(file)) {
      _.forEach(file, function() {

      })
    } else {

    }
  },

  write: function() {
    // TODO - write to FS
  }
}

hazy.pattern = {
  pool: {},

  appliesTo: function(stub) { // determines if a seed can be populated to the provided function
    return this.pool.hasOwnProperty(stub)
  },

  register: function(path, value) {
    this.pool[path] = value
  },

  registerConfig: function(patternConfig) {
    var stubName       = patternConfig.stub,
        patternPath    = patternConfig.path,
        patternHandler = patternConfig.handler,
        patternKey     = stubName || stubPath

    if (!_.contains(this.pool, stubName)) {
      throw 'Stub is not registered in pool, failed to register pattern ' + stubName
    }

    this.pool[patternKey] = {name: stubName, path: stubPath, handler: patternHandler}
  }
}

hazy.seed   = _.cloneDeep(hazy.pattern)
hazy.filter = _.cloneDeep(hazy.pattern)
<|endoftext|>


<commit_before>;(function ($$) {
  "use strict";

  /*  Min and Max heap predefaults */

  $$.Minheap = function (cy, eles, valueFn) {
    return new $$.Heap(cy, eles, $$.Heap.minHeapComparator, valueFn);
  };

  $$.Maxheap = function (cy, eles, valueFn) {
    return new $$.Heap(cy, eles, $$.Heap.maxHeapComparator, valueFn);
  };

  $$.Heap = function (cy, eles, comparator, valueFn) {
    if (typeof comparator === "undefined" || typeof eles === "undefined") {
      return;
    }

    if (typeof valueFn === "undefined") {
      valueFn = $$.Heap.idFn;
    }

    var sourceHeap = [],
      pointers = {},
      elements = [],
      i = 0,
      id,
      heap,
      elesLen;

    eles = this.getArgumentAsCollection(eles, cy);
    elesLen = eles.length;

    for (i = 0; i < elesLen; i += 1) {
      sourceHeap.push(valueFn.call(cy, eles[i], i, eles));

      id = eles[i].id();

      if (pointers.hasOwnProperty(id)) {
        throw "ERROR: Multiple items with the same id found: " + id;
      }

      pointers[id] = i;
      elements.push(id);
    }

    this._private = {
      cy: cy,
      heap: sourceHeap,
      pointers: pointers,
      elements: elements,
      comparator: comparator,
      extractor: valueFn,
      length: elesLen
    };

    for (i = Math.floor(elesLen / 2); i >= 0; i -= 1) {
      heap = this.heapify(i);
    }

    return heap;
  };

  /* static methods */
  $$.Heap.idFn = function (node) {
    return node.id();
  };

  $$.Heap.minHeapComparator = function (a, b) {
    return a >= b;
  };

  $$.Heap.maxHeapComparator = function (a, b) {
    return a <= b;
  };

  /* object methods */
  $$.Heap.prototype.size = function () {
    return this._private.length;
  };

  $$.Heap.prototype.getArgumentAsCollection = function (eles, cy) {
    var result;
    if(typeof cy === "undefined") {
      cy = this._private.cy;
    }

    if ($$.is.elementOrCollection(eles)) {
      result = eles;

    } else {
      var resultArray = [],
        sourceEles = [].concat.apply([], [eles]);

      for (var i = 0; i < sourceEles.length; i++) {
        var id = sourceEles[i],
          ele = cy.getElementById(id);

        if(ele.length > 0) {
          resultArray.push(ele);
        }
      }

      result = new $$.Collection(cy, resultArray);
    }

    return result;
  };

  $$.Heap.prototype.isHeap = function () {
    var array = this._private.heap,
      arrlen = array.length,
      i,
      left,
      right,
      lCheck,
      rCheck,
      comparator = this._private.comparator;

    for (i = 0; i < arrlen; i += 1) {
      left = 2 * i + 1;
      right = left + 1;
      lCheck = left < arrlen ? comparator(array[left], array[i]) : true;
      rCheck = right < arrlen ? comparator(array[right], array[i]) : true;

      if (!lCheck || !rCheck) {
        return false;
      }
    }

    return true;
  };

  $$.Heap.prototype.heapSwap = function (i, j) {
    var heap = this._private.heap,
      pointers = this._private.pointers,
      elements = this._private.elements,
      swapValue = heap[i],
      swapElems = elements[i],
      idI = elements[i],
      idJ = elements[j];

    heap[i] = heap[j];
    elements[i] = elements[j];

    pointers[idI] = j;
    pointers[idJ] = i;

    heap[j] = swapValue;
    elements[j] = swapElems;
  };

  $$.Heap.prototype.heapify = function (i, rootToLeaf) {
    var treeLen = 0,
      condHeap = false,
      array,
      pointers,
      current,
      left,
      right,
      best,
      tmp,
      comparator,
      parent;

    if (typeof rootToLeaf === "undefined") {
      rootToLeaf = true;
    }

    array = this._private.heap;
    treeLen = array.length;
    comparator = this._private.comparator;
    current = i;

    while (!condHeap) {

      if (rootToLeaf) {
        left = 2 * current + 1;
        right = left + 1;
        best = current;

        if (left < treeLen && !comparator(array[left], array[best])) {
          best = left;
        }

        if (right < treeLen && !comparator(array[right], array[best])) {
          best = right;
        }

        condHeap = best === current;

        if (!condHeap) {
          this.heapSwap(best, current);
          current = best;
        }

      } else {
        parent = Math.floor((current - 1) / 2);
        best = current;
        condHeap = parent < 0 || comparator(array[best], array[parent]);

        if (!condHeap) {
          this.heapSwap(best, parent);
          current = parent;
        }
      }

    } // while
  };

  /* collectionOrElement */
  $$.Heap.prototype.insert = function (eles) {
    var elements = this.getArgumentAsCollection(eles),
      elsize = elements.length,
      element,
      elindex,
      elvalue,
      elid,
      i;

    for (i = 0; i < elsize; i += 1) {
      element = elements[i];
      elindex = this._private.heap.length;
      elvalue = this._private.extractor(element);
      elid = element.id();

      if (this._private.pointers.hasOwnProperty(elid)) {
        throw "ERROR: Multiple items with the same id found: " + elid;
      }

      this._private.heap.push(elvalue);
      this._private.elements.push(elid);
      this._private.pointers[elid] = elindex;
      this.heapify(elindex, false);
    }

    this._private.length = this._private.heap.length;
  };

  $$.Heap.prototype.getValueById = function (elementId) {
    if (this._private.pointers.hasOwnProperty(elementId)) {
      var elementIndex = this._private.pointers[elementId];

      return this._private.heap[elementIndex];
    }
  };

  $$.Heap.prototype.contains = function (eles) {
    var elements = this.getArgumentAsCollection(eles);

    for (var i = 0; i < elements.length; i += 1) {
      var elementId = elements[i].id();

      if(!this._private.pointers.hasOwnProperty(elementId)) {
        return false;
      }
    }

    return true;
  };

  $$.Heap.prototype.top = function () {
    if (this._private.length > 0) {

      return {
        value: this._private.heap[0],
        id: this._private.elements[0]
      };

    }
  };

  $$.Heap.prototype.pop = function () {
    if (this._private.length > 0) {
      var top = this.top(),
        lastIndex = this._private.length - 1,
        removeCandidate,
        removeValue,
        remId;

      this.heapSwap(0, lastIndex);

      removeCandidate = this._private.elements[lastIndex];
      removeValue = this._private.heap[lastIndex];
      remId = removeCandidate;

      this._private.heap.pop();
      this._private.elements.pop();
      this._private.length = this._private.heap.length;
      delete this._private.pointers[remId];

      this.heapify(0);
      return top;
    }
  };

  $$.Heap.prototype.findDirectionHeapify = function (index) {
    var parent = Math.floor((index - 1) / 2),
      array = this._private.heap,
      condHeap = parent < 0 || this._private.comparator(array[index], array[parent]);

    this.heapify(index, condHeap);
  };

  /* edit is a new value or function */
  // only values in heap are updated. elements themselves are not!
  $$.Heap.prototype.edit = function (eles, edit) {
    var elements = this.getArgumentAsCollection(eles);

    for (var i = 0; i < elements.length; i += 1) {
      var elementId = elements[i].id(),
        elementIndex = this._private.pointers[elementId],
        elementValue = this._private.heap[elementIndex];

      if ($$.is.number(edit)) {
        this._private.heap[elementIndex] = edit;

      } else if ($$.is.fn(edit)) {
        this._private.heap[elementIndex] = edit.call(this._private.cy, elementValue, elementIndex);
      }

      this.findDirectionHeapify(elementIndex);
    }
  };

  $$.Heap.prototype.delete = function (eles) {
    var elements = this.getArgumentAsCollection(eles);

    for (var i = 0; i < elements.length; i += 1) {
      var elementId = elements[i].id(),
        elementIndex = this._private.pointers[elementId],
        lastIndex = this._private.length - 1,
        removeCandidate,
        removeValue,
        remId;

      if (elementIndex !== lastIndex) {
        this.heapSwap(elementIndex, lastIndex);
      }

      removeCandidate = this._private.elements[lastIndex];
      removeValue = this._private.heap[lastIndex];
      remId = removeCandidate;

      this._private.heap.pop();
      this._private.elements.pop();
      this._private.length = this._private.heap.length;
      delete this._private.pointers[remId];

      this.findDirectionHeapify(elementIndex);
    }

    return removeValue;
  };

})(cytoscape);<commit_msg>consistency changes<commit_after>;(function ($$) {
  "use strict";

  /*  Min and Max heap predefaults */

  $$.Minheap = function (cy, eles, valueFn) {
    return new $$.Heap(cy, eles, $$.Heap.minHeapComparator, valueFn);
  };

  $$.Maxheap = function (cy, eles, valueFn) {
    return new $$.Heap(cy, eles, $$.Heap.maxHeapComparator, valueFn);
  };

  $$.Heap = function (cy, eles, comparator, valueFn) {
    if (typeof comparator === "undefined" || typeof eles === "undefined") {
      return;
    }

    if (typeof valueFn === "undefined") {
      valueFn = $$.Heap.idFn;
    }

    var sourceHeap = [],
      pointers = {},
      elements = [],
      i = 0,
      id,
      heap,
      elesLen;

    eles = this.getArgumentAsCollection(eles, cy);
    elesLen = eles.length;

    for (i = 0; i < elesLen; i += 1) {
      sourceHeap.push(valueFn.call(cy, eles[i], i, eles));

      id = eles[i].id();

      if (pointers.hasOwnProperty(id)) {
        throw "ERROR: Multiple items with the same id found: " + id;
      }

      pointers[id] = i;
      elements.push(id);
    }

    this._private = {
      cy: cy,
      heap: sourceHeap,
      pointers: pointers,
      elements: elements,
      comparator: comparator,
      extractor: valueFn,
      length: elesLen
    };

    for (i = Math.floor(elesLen / 2); i >= 0; i -= 1) {
      heap = this.heapify(i);
    }

    return heap;
  };

  /* static methods */
  $$.Heap.idFn = function (node) {
    return node.id();
  };

  $$.Heap.minHeapComparator = function (a, b) {
    return a >= b;
  };

  $$.Heap.maxHeapComparator = function (a, b) {
    return a <= b;
  };

  $$.fn.heap = function( fnMap, options ){
    for( var name in fnMap ){
      var fn = fnMap[name];
      $$.Heap.prototype[ name ] = fn;
    }
  };

  $$.heapfn = $$.Heap.prototype; // short alias

  /* object methods */
  $$.heapfn.size = function () {
    return this._private.length;
  };

  $$.heapfn.getArgumentAsCollection = function (eles, cy) {
    var result;
    if(typeof cy === "undefined") {
      cy = this._private.cy;
    }

    if ($$.is.elementOrCollection(eles)) {
      result = eles;

    } else {
      var resultArray = [],
        sourceEles = [].concat.apply([], [eles]);

      for (var i = 0; i < sourceEles.length; i++) {
        var id = sourceEles[i],
          ele = cy.getElementById(id);

        if(ele.length > 0) {
          resultArray.push(ele);
        }
      }

      result = new $$.Collection(cy, resultArray);
    }

    return result;
  };

  $$.heapfn.isHeap = function () {
    var array = this._private.heap,
      arrlen = array.length,
      i,
      left,
      right,
      lCheck,
      rCheck,
      comparator = this._private.comparator;

    for (i = 0; i < arrlen; i += 1) {
      left = 2 * i + 1;
      right = left + 1;
      lCheck = left < arrlen ? comparator(array[left], array[i]) : true;
      rCheck = right < arrlen ? comparator(array[right], array[i]) : true;

      if (!lCheck || !rCheck) {
        return false;
      }
    }

    return true;
  };

  $$.heapfn.heapSwap = function (i, j) {
    var heap = this._private.heap,
      pointers = this._private.pointers,
      elements = this._private.elements,
      swapValue = heap[i],
      swapElems = elements[i],
      idI = elements[i],
      idJ = elements[j];

    heap[i] = heap[j];
    elements[i] = elements[j];

    pointers[idI] = j;
    pointers[idJ] = i;

    heap[j] = swapValue;
    elements[j] = swapElems;
  };

  $$.heapfn.heapify = function (i, rootToLeaf) {
    var treeLen = 0,
      condHeap = false,
      array,
      pointers,
      current,
      left,
      right,
      best,
      tmp,
      comparator,
      parent;

    if (typeof rootToLeaf === "undefined") {
      rootToLeaf = true;
    }

    array = this._private.heap;
    treeLen = array.length;
    comparator = this._private.comparator;
    current = i;

    while (!condHeap) {

      if (rootToLeaf) {
        left = 2 * current + 1;
        right = left + 1;
        best = current;

        if (left < treeLen && !comparator(array[left], array[best])) {
          best = left;
        }

        if (right < treeLen && !comparator(array[right], array[best])) {
          best = right;
        }

        condHeap = best === current;

        if (!condHeap) {
          this.heapSwap(best, current);
          current = best;
        }

      } else {
        parent = Math.floor((current - 1) / 2);
        best = current;
        condHeap = parent < 0 || comparator(array[best], array[parent]);

        if (!condHeap) {
          this.heapSwap(best, parent);
          current = parent;
        }
      }

    } // while
  };

  /* collectionOrElement */
  $$.heapfn.insert = function (eles) {
    var elements = this.getArgumentAsCollection(eles),
      elsize = elements.length,
      element,
      elindex,
      elvalue,
      elid,
      i;

    for (i = 0; i < elsize; i += 1) {
      element = elements[i];
      elindex = this._private.heap.length;
      elvalue = this._private.extractor(element);
      elid = element.id();

      if (this._private.pointers.hasOwnProperty(elid)) {
        throw "ERROR: Multiple items with the same id found: " + elid;
      }

      this._private.heap.push(elvalue);
      this._private.elements.push(elid);
      this._private.pointers[elid] = elindex;
      this.heapify(elindex, false);
    }

    this._private.length = this._private.heap.length;
  };

  $$.heapfn.getValueById = function (elementId) {
    if (this._private.pointers.hasOwnProperty(elementId)) {
      var elementIndex = this._private.pointers[elementId];

      return this._private.heap[elementIndex];
    }
  };

  $$.heapfn.contains = function (eles) {
    var elements = this.getArgumentAsCollection(eles);

    for (var i = 0; i < elements.length; i += 1) {
      var elementId = elements[i].id();

      if(!this._private.pointers.hasOwnProperty(elementId)) {
        return false;
      }
    }

    return true;
  };

  $$.heapfn.top = function () {
    if (this._private.length > 0) {

      return {
        value: this._private.heap[0],
        id: this._private.elements[0]
      };

    }
  };

  $$.heapfn.pop = function () {
    if (this._private.length > 0) {
      var top = this.top(),
        lastIndex = this._private.length - 1,
        removeCandidate,
        removeValue,
        remId;

      this.heapSwap(0, lastIndex);

      removeCandidate = this._private.elements[lastIndex];
      removeValue = this._private.heap[lastIndex];
      remId = removeCandidate;

      this._private.heap.pop();
      this._private.elements.pop();
      this._private.length = this._private.heap.length;
      delete this._private.pointers[remId];

      this.heapify(0);
      return top;
    }
  };

  $$.heapfn.findDirectionHeapify = function (index) {
    var parent = Math.floor((index - 1) / 2),
      array = this._private.heap,
      condHeap = parent < 0 || this._private.comparator(array[index], array[parent]);

    this.heapify(index, condHeap);
  };

  /* edit is a new value or function */
  // only values in heap are updated. elements themselves are not!
  $$.heapfn.edit = function (eles, edit) {
    var elements = this.getArgumentAsCollection(eles);

    for (var i = 0; i < elements.length; i += 1) {
      var elementId = elements[i].id(),
        elementIndex = this._private.pointers[elementId],
        elementValue = this._private.heap[elementIndex];

      if ($$.is.number(edit)) {
        this._private.heap[elementIndex] = edit;

      } else if ($$.is.fn(edit)) {
        this._private.heap[elementIndex] = edit.call(this._private.cy, elementValue, elementIndex);
      }

      this.findDirectionHeapify(elementIndex);
    }
  };

  $$.heapfn.delete = function (eles) {
    var elements = this.getArgumentAsCollection(eles);

    for (var i = 0; i < elements.length; i += 1) {
      var elementId = elements[i].id(),
        elementIndex = this._private.pointers[elementId],
        lastIndex = this._private.length - 1,
        removeCandidate,
        removeValue,
        remId;

      if (elementIndex !== lastIndex) {
        this.heapSwap(elementIndex, lastIndex);
      }

      removeCandidate = this._private.elements[lastIndex];
      removeValue = this._private.heap[lastIndex];
      remId = removeCandidate;

      this._private.heap.pop();
      this._private.elements.pop();
      this._private.length = this._private.heap.length;
      delete this._private.pointers[remId];

      this.findDirectionHeapify(elementIndex);
    }

    return removeValue;
  };

})(cytoscape);<|endoftext|>


<commit_before>import Port from './port';
import {default as resizer} from 'iframe-resizer';

var originRe = /^(http:\/\/|https:\/\/)[^\/]+/i;

export default class Host extends Port {
	constructor(elementProvider, src, options) {

		var origin = Host.tryGetOrigin(src);
		if(origin === null) {
			throw new Error(`Unable to extract origin from "${src}"`);
		}

		var parent = elementProvider();
		if (parent === null) {
			throw new Error(`Could not find parent node`);
		}

		var iframe = Host.createIFrame(src);
		parent.appendChild(iframe);

		super(iframe.contentWindow, origin, options);

		this.iframe = iframe;

		this.resizer = null;
	}
	connect() {
		var me = this;
		return new Promise((resolve, reject) => {
			me.onEvent('ready', function() {
				super.connect();
				me.resizer = resizer.iframeResizer({}, me.iframe);
				resolve();
			}).onEvent('title', function(title) {
				document.title = title;
			}).onEvent('navigate', function(url) {
				document.location.href = url;
			});
			super.open();
		});
	}
	close() {
		super.close();
		this.resizer.close(this.iframe);
	}
	static createIFrame(src) {
		var iframe = document.createElement('iframe');
		iframe.width = '100%';
		iframe.style.border = 'none';
		iframe.style.overflow = 'hidden';
		iframe.scrolling = 'no';
		iframe.src = src;
		return iframe;
	}
	static tryGetOrigin(url) {
		if(url && url.indexOf('//') === 0) {
			url = window.location.protocol + url;
		}
		var match = originRe.exec(url);
		return (match !== null) ? match[0] : null;
	}
}
<commit_msg>passing debug flag down to iframe resize and using "max" resize method<commit_after>import Port from './port';
import {default as resizer} from 'iframe-resizer';

var originRe = /^(http:\/\/|https:\/\/)[^\/]+/i;

export default class Host extends Port {
	constructor(elementProvider, src, options) {

		var origin = Host.tryGetOrigin(src);
		if(origin === null) {
			throw new Error(`Unable to extract origin from "${src}"`);
		}

		var parent = elementProvider();
		if (parent === null) {
			throw new Error(`Could not find parent node`);
		}

		var iframe = Host.createIFrame(src);
		parent.appendChild(iframe);

		super(iframe.contentWindow, origin, options);

		this.iframe = iframe;

		this.resizer = null;
	}
	connect() {
		var me = this;
		return new Promise((resolve, reject) => {
			me.onEvent('ready', function() {
				super.connect();
				me.resizer = resizer.iframeResizer(
					{
						log: me.debugEnabled
					},
					me.iframe
				);
				resolve();
			}).onEvent('title', function(title) {
				document.title = title;
			}).onEvent('navigate', function(url) {
				document.location.href = url;
			});
			super.open();
		});
	}
	close() {
		super.close();
		this.resizer.close(this.iframe);
	}
	static createIFrame(src) {
		var iframe = document.createElement('iframe');
		iframe.width = '100%';
		iframe.style.border = 'none';
		iframe.style.overflow = 'hidden';
		iframe.scrolling = 'no';
		iframe.src = src;
		return iframe;
	}
	static tryGetOrigin(url) {
		if(url && url.indexOf('//') === 0) {
			url = window.location.protocol + url;
		}
		var match = originRe.exec(url);
		return (match !== null) ? match[0] : null;
	}
}
<|endoftext|>


<commit_before>'use strict'

import {Blueprint} from './apib'
import * as env from './env'
import * as io from './io'

import hazy from 'hazy'
import cheerio from 'cheerio'
import aglio from 'aglio'

import _ from 'lodash'

import {logger} from './log'

export class Document {

  constructor(html: String) {
    this.html = html
  }

  get config(): Object {
    return Document.config()
  }

  get query(): Object {
    return Document.query(this.html)
  }

  get main(): String {
    return Document.main(this.html)
  }

  get stripped(): String {
    return Document.stripped(this.html)
  }

  get filtered(): String {
    return Document.filtered(this.html)
  }

  dest(filepath?: String, html?: String): Promise {
    return Document.dest(filepath || this.config.dest, html || this.html)
  }

  static config(): Object {
    return env.current().view
  }

  static elementConfig(configKey: String): Object {
    const config = Document.config().elements[configKey]

    if (_.isArray(config) && !_.isEmpty(config)) {
      return config.join(' ').trim()
    }

    return config
  }

  static query(html: String): Object {
    return cheerio.load(html)
  }

  static container(html: String): Object {
    log().info('extracting main container element')

    const selector = Document.elementConfig('container')
    const query    = Document.query(html)(selector)

    return query
  }

  static stripped(html: String): Object {
    log().info('stripping configured elements')

    const selector = Document.elementConfig('strip')
    const query    = Document.query(html)

    if (selector)
      query(selector).remove()

    return query
  }

  static filtered(html: String): Object { // TODO - change to 'process'
    log().info('applying HTML filters')

    const containerDom = Document.container(html)
    const bakedDom = Document.stripped(containerDom.html())

    return bakedDom
  }

  static dest(filepath: String, html: String): Promise {
    return new Promise((resolve, reject) => {
      if (filepath) {
        io.util.fs
          .dest(filepath, html)
          .then(resolve)
          .catch(reject)
      } else {
        reject('HTML filepath required')
      }
    })
  }

  static fromBlueprints(blueprints: Array): Promise {
    return Promise.all(blueprints.map(bp => Document.fromBlueprint(bp)))
  }

  static fromBlueprint(blueprint: Blueprint): Promise {
    return new Promise((resolve, reject) => {
      log('aglio').info('creating html from API blueprint')

      if (blueprint instanceof Blueprint && blueprint.compiled) {
        const locals  = {blot: env.current().name, fixtures: blueprint.compiled.fixtures}
        const options = _.merge({locals}, Document.config().options)

        aglio.render(blueprint.compiled.markdown, options, (err, html, warnings) => {
          if (!_.isEmpty(warnings)) {
            log('aglio').warn(`aglio warned: ${warnings}`)
          }

          if (!err) {
            log('aglio').info('parsed as html')

            resolve(new Document(html))
          } else {
            log('aglio').error(`aglio errored: ${err}`)

            reject(err)
          }
        })
      } else {
        reject('compiled API blueprint required')
      }
    })
  }

}

export const log = (sub) => logger().child({module: sub ? `html.${sub}` : 'html'})
<commit_msg>:bug: fixed primary selector delimiter<commit_after>'use strict'

import {Blueprint} from './apib'
import * as env from './env'
import * as io from './io'

import hazy from 'hazy'
import cheerio from 'cheerio'
import aglio from 'aglio'

import _ from 'lodash'

import {logger} from './log'

export class Document {

  constructor(html: String) {
    this.html = html
  }

  get config(): Object {
    return Document.config()
  }

  get query(): Object {
    return Document.query(this.html)
  }

  get main(): String {
    return Document.main(this.html)
  }

  get stripped(): String {
    return Document.stripped(this.html)
  }

  get filtered(): String {
    return Document.filtered(this.html)
  }

  dest(filepath?: String, html?: String): Promise {
    return Document.dest(filepath || this.config.dest, html || this.html)
  }

  static config(): Object {
    return env.current().view
  }

  static elementConfig(configKey: String): Object {
    const config = Document.config().elements[configKey]

    if (_.isArray(config) && !_.isEmpty(config)) {
      return config.length > 1 ? config.join(', ').trim() : config[0]
    }

    return config
  }

  static query(html: String): Object {
    return cheerio.load(html)
  }

  static container(html: String): Object {
    log().info('extracting main container element')

    const selector = Document.elementConfig('container')
    const query    = Document.query(html)(selector)

    return query
  }

  static stripped(html: String): Object {
    log().info('stripping configured elements')

    const selector = Document.elementConfig('strip')
    const query    = Document.query(html)

    if (selector)
      query(selector).remove()

    return query
  }

  static filtered(html: String): Object { // TODO - change to 'process'
    log().info('applying HTML filters')

    const containerDom = Document.container(html)
    const bakedDom = Document.stripped(containerDom.html())

    return bakedDom
  }

  static dest(filepath: String, html: String): Promise {
    return new Promise((resolve, reject) => {
      if (filepath) {
        io.util.fs
          .dest(filepath, html)
          .then(resolve)
          .catch(reject)
      } else {
        reject('HTML filepath required')
      }
    })
  }

  static fromBlueprints(blueprints: Array): Promise {
    return Promise.all(blueprints.map(bp => Document.fromBlueprint(bp)))
  }

  static fromBlueprint(blueprint: Blueprint): Promise {
    return new Promise((resolve, reject) => {
      log('aglio').info('creating html from API blueprint')

      if (blueprint instanceof Blueprint && blueprint.compiled) {
        const locals  = {blot: env.current().name, fixtures: blueprint.compiled.fixtures}
        const options = _.merge({locals}, Document.config().options)

        aglio.render(blueprint.compiled.markdown, options, (err, html, warnings) => {
          if (!_.isEmpty(warnings)) {
            log('aglio').warn(`aglio warned: ${warnings}`)
          }

          if (!err) {
            log('aglio').info('parsed as html')

            resolve(new Document(html))
          } else {
            log('aglio').error(`aglio errored: ${err}`)

            reject(err)
          }
        })
      } else {
        reject('compiled API blueprint required')
      }
    })
  }

}

export const log = (sub) => logger().child({module: sub ? `html.${sub}` : 'html'})
<|endoftext|>


<commit_before>/**
 * ACME HTTP client
 */

const crypto = require('crypto');
const debug = require('debug')('acme-client');
const axios = require('./axios');
const util = require('./util');
const forge = require('./crypto/forge');

/**
 * ACME HTTP client
 *
 * @class
 * @param {string} directoryUrl ACME directory URL
 * @param {buffer} accountKey PEM encoded account private key
 */

class HttpClient {
    constructor(directoryUrl, accountKey) {
        this.directoryUrl = directoryUrl;
        this.accountKey = accountKey;

        this.directory = null;
        this.jwk = null;
    }

    /**
     * HTTP request
     *
     * @param {string} url HTTP URL
     * @param {string} method HTTP method
     * @param {object} [opts] Request options
     * @returns {Promise<object>} HTTP response
     */

    async request(url, method, opts = {}) {
        opts.url = url;
        opts.method = method;
        opts.validateStatus = null;

        /* Headers */
        if (typeof opts.headers === 'undefined') {
            opts.headers = {};
        }

        opts.headers['Content-Type'] = 'application/jose+json';

        /* Request */
        debug(`HTTP request: ${method} ${url}`);
        const resp = await axios.request(opts);

        debug(`RESP ${resp.status} ${method} ${url}`);
        return resp;
    }

    /**
     * Ensure provider directory exists
     *
     * https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md#directory
     *
     * @returns {Promise}
     */

    async getDirectory() {
        if (!this.directory) {
            const resp = await this.request(this.directoryUrl, 'get');
            this.directory = resp.data;
        }
    }

    /**
     * Get JSON Web Key
     *
     * @returns {Promise<object>} {e, kty, n}
     */

    async getJwk() {
        if (this.jwk) {
            return this.jwk;
        }

        const exponent = await forge.getPublicExponent(this.accountKey);
        const modulus = await forge.getModulus(this.accountKey);

        this.jwk = {
            e: util.b64encode(exponent),
            kty: 'RSA',
            n: util.b64encode(modulus)
        };

        return this.jwk;
    }

    /**
     * Get nonce from directory API endpoint
     *
     * https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md#getting-a-nonce
     *
     * @returns {Promise<string>} nonce
     */

    async getNonce() {
        const url = await this.getResourceUrl('newNonce');
        const resp = await this.request(url, 'head');

        if (!resp.headers['replay-nonce']) {
            throw new Error('Failed to get nonce from ACME provider');
        }

        return resp.headers['replay-nonce'];
    }

    /**
     * Get URL for a directory resource
     *
     * @param {string} resource API resource name
     * @returns {Promise<string>} URL
     */

    async getResourceUrl(resource) {
        await this.getDirectory();

        if (!this.directory[resource]) {
            throw new Error(`Could not resolve URL for API resource: "${resource}"`);
        }

        return this.directory[resource];
    }

    /**
     * Create signed HTTP request body
     *
     * @param {string} url Request URL
     * @param {object} payload Request payload
     * @param {string} [nonce] Request nonce
     * @returns {Promise<object>} Signed HTTP request body
     */

    async createSignedBody(url, payload, nonce = null, kid = null) {
        /* JWS header */
        const header = {
            url,
            alg: 'RS256'
        };

        if (nonce) {
            debug(`Using nonce: ${nonce}`);
            header.nonce = nonce;
        }

        /* KID or JWK */
        if (kid) {
            header.kid = kid;
        }
        else {
            header.jwk = await this.getJwk();
        }

        /* Request payload */
        let result;
        if (payload === "") {
            result = {
                payload: "",
                protected: util.b64encode(JSON.stringify(header))
            };
        }
        else {
            result = {
                payload: util.b64encode(JSON.stringify(payload)),
                protected: util.b64encode(JSON.stringify(header))
            };
        }

        /* Signature */
        const signer = crypto.createSign('RSA-SHA256').update(`${result.protected}.${result.payload}`, 'utf8');
        result.signature = util.b64escape(signer.sign(this.accountKey, 'base64'));

        return result;
    }

    /**
     * Signed HTTP request
     *
     * https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md#request-authentication
     *
     * @param {string} url Request URL
     * @param {string} method HTTP method
     * @param {object} payload Request payload
     * @param {string} [kid] KID
     * @returns {Promise<object>} HTTP response
     */

    async signedRequest(url, method, payload, kid = null) {
        const nonce = await this.getNonce();
        const data = await this.createSignedBody(url, payload, nonce, kid);
        return this.request(url, method, { data });
    }
}

/* Export client */
module.exports = HttpClient;
<commit_msg>use single quotes<commit_after>/**
 * ACME HTTP client
 */

const crypto = require('crypto');
const debug = require('debug')('acme-client');
const axios = require('./axios');
const util = require('./util');
const forge = require('./crypto/forge');

/**
 * ACME HTTP client
 *
 * @class
 * @param {string} directoryUrl ACME directory URL
 * @param {buffer} accountKey PEM encoded account private key
 */

class HttpClient {
    constructor(directoryUrl, accountKey) {
        this.directoryUrl = directoryUrl;
        this.accountKey = accountKey;

        this.directory = null;
        this.jwk = null;
    }

    /**
     * HTTP request
     *
     * @param {string} url HTTP URL
     * @param {string} method HTTP method
     * @param {object} [opts] Request options
     * @returns {Promise<object>} HTTP response
     */

    async request(url, method, opts = {}) {
        opts.url = url;
        opts.method = method;
        opts.validateStatus = null;

        /* Headers */
        if (typeof opts.headers === 'undefined') {
            opts.headers = {};
        }

        opts.headers['Content-Type'] = 'application/jose+json';

        /* Request */
        debug(`HTTP request: ${method} ${url}`);
        const resp = await axios.request(opts);

        debug(`RESP ${resp.status} ${method} ${url}`);
        return resp;
    }

    /**
     * Ensure provider directory exists
     *
     * https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md#directory
     *
     * @returns {Promise}
     */

    async getDirectory() {
        if (!this.directory) {
            const resp = await this.request(this.directoryUrl, 'get');
            this.directory = resp.data;
        }
    }

    /**
     * Get JSON Web Key
     *
     * @returns {Promise<object>} {e, kty, n}
     */

    async getJwk() {
        if (this.jwk) {
            return this.jwk;
        }

        const exponent = await forge.getPublicExponent(this.accountKey);
        const modulus = await forge.getModulus(this.accountKey);

        this.jwk = {
            e: util.b64encode(exponent),
            kty: 'RSA',
            n: util.b64encode(modulus)
        };

        return this.jwk;
    }

    /**
     * Get nonce from directory API endpoint
     *
     * https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md#getting-a-nonce
     *
     * @returns {Promise<string>} nonce
     */

    async getNonce() {
        const url = await this.getResourceUrl('newNonce');
        const resp = await this.request(url, 'head');

        if (!resp.headers['replay-nonce']) {
            throw new Error('Failed to get nonce from ACME provider');
        }

        return resp.headers['replay-nonce'];
    }

    /**
     * Get URL for a directory resource
     *
     * @param {string} resource API resource name
     * @returns {Promise<string>} URL
     */

    async getResourceUrl(resource) {
        await this.getDirectory();

        if (!this.directory[resource]) {
            throw new Error(`Could not resolve URL for API resource: "${resource}"`);
        }

        return this.directory[resource];
    }

    /**
     * Create signed HTTP request body
     *
     * @param {string} url Request URL
     * @param {object} payload Request payload
     * @param {string} [nonce] Request nonce
     * @returns {Promise<object>} Signed HTTP request body
     */

    async createSignedBody(url, payload, nonce = null, kid = null) {
        /* JWS header */
        const header = {
            url,
            alg: 'RS256'
        };

        if (nonce) {
            debug(`Using nonce: ${nonce}`);
            header.nonce = nonce;
        }

        /* KID or JWK */
        if (kid) {
            header.kid = kid;
        }
        else {
            header.jwk = await this.getJwk();
        }

        /* Request payload */
        let result;
        if (payload === '') {
            result = {
                payload: '',
                protected: util.b64encode(JSON.stringify(header))
            };
        }
        else {
            result = {
                payload: util.b64encode(JSON.stringify(payload)),
                protected: util.b64encode(JSON.stringify(header))
            };
        }

        /* Signature */
        const signer = crypto.createSign('RSA-SHA256').update(`${result.protected}.${result.payload}`, 'utf8');
        result.signature = util.b64escape(signer.sign(this.accountKey, 'base64'));

        return result;
    }

    /**
     * Signed HTTP request
     *
     * https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md#request-authentication
     *
     * @param {string} url Request URL
     * @param {string} method HTTP method
     * @param {object} payload Request payload
     * @param {string} [kid] KID
     * @returns {Promise<object>} HTTP response
     */

    async signedRequest(url, method, payload, kid = null) {
        const nonce = await this.getNonce();
        const data = await this.createSignedBody(url, payload, nonce, kid);
        return this.request(url, method, { data });
    }
}

/* Export client */
module.exports = HttpClient;
<|endoftext|>


<commit_before>import path from 'path';
import { all, promisifyAll, resolve } from 'bluebird';
import osLocale from 'os-locale';
import { curry, propOr, replace } from 'ramda';

const fs = promisifyAll(require('fs'));

/**
 * Returns the user locale. Firstly consider the env variable and, if it
 * doesn't exist, consider machine's locale
 *
 * @return {Promise}
 */
export function getLocale() {
    const { RUNG_LOCALE } = process.env;
    return resolve(RUNG_LOCALE ? RUNG_LOCALE : osLocale());
}

/**
 * Translates a string or fallback to the key
 *
 * @param {Object} map - Object containing extension strings
 * @param {String} key - Key to search in hashmap
 * @return {String}
 */
export const translator = curry((map, key, params = {}) => {
    const sentence = propOr(key, key, map);

    return replace(
        /{{(\w+)}}/g,
        (full, partial) => params[partial] || full,
        sentence
    );
});

/**
 * Reads the JSON file corresponding to a specific locale
 *
 * @return {Promise}
 */
export function getLocaleStrings() {
    return getLocale()
        .then(locale => {
            const localePath = path.join('locales', `${locale}.json`);
            return all([fs.lstatAsync(localePath), localePath]);
        })
        .spread((lstat, localePath) => lstat.isFile()
            ? fs.readFileAsync(localePath).then(JSON.parse)
            : {})
        .catchReturn({});
}
<commit_msg>Remove unnecessary verification for locales<commit_after>import path from 'path';
import fs from 'fs';
import { all, promisify, resolve } from 'bluebird';
import osLocale from 'os-locale';
import { curry, propOr, replace } from 'ramda';

const readFile = promisify(fs.readFile);

/**
 * Returns the user locale. Firstly consider the env variable and, if it
 * doesn't exist, consider machine's locale
 *
 * @return {Promise}
 */
export function getLocale() {
    const { RUNG_LOCALE } = process.env;
    return resolve(RUNG_LOCALE ? RUNG_LOCALE : osLocale());
}

/**
 * Translates a string or fallback to the key
 *
 * @param {Object} map - Object containing extension strings
 * @param {String} key - Key to search in hashmap
 * @return {String}
 */
export const translator = curry((map, key, params = {}) => {
    const sentence = propOr(key, key, map);

    return replace(
        /{{(\w+)}}/g,
        (full, partial) => params[partial] || full,
        sentence
    );
});

/**
 * Reads the JSON file corresponding to a specific locale
 *
 * @return {Promise}
 */
export function getLocaleStrings() {
    return getLocale()
        .then(locale => readFile(path.join('locales', `${locale}.json`)))
        .then(JSON.parse)
        .catchReturn({});
}
<|endoftext|>


<commit_before>/**
 *
 * jcon
 *
 * A JavaScript parser combinator Library
 *
 */
var jcon = (function(undefined){

    var slice = Array.prototype.slice;

    function Parser(f){

        return jFunction.create({
            /**
             * @method parse
             *
             */
            parse: function(){
                return this.__fun__.apply(this, arguments);
            },

            /**
             * @method seq
             *
             * @param {Array:Parser}
             *
             * @desc 使用this指向的当前解析器，和arguments中的解析器，进行连接运算，产生新的连接解析器
             *
             */
            seq: function(){
                var args = slice.call(arguments, 0);
                args.unshift(this);
                return jcon.seq.apply(jcon, args);
            },

            /**
             * @method or
             *
             * @param {Array:Parser}
             *
             * @desc 使用this指向的当前解析器，和arguments中的解析器，进行或运算，产生新的或解析器
             *
             */
            or: function(){
                var args = slice.call(arguments, 0);
                args.unshift(this);
                return jcon.or.apply(jcon, args);
            },

            /**
             *
             * @method times
             *
             * @param {number} min
             * @param {number} max
             *
             * @desc 返回this指向的当前parser的min到max次解析的解析器
             *
             */
            times: function(min, max){
                return jcon.times(this, min, max);
            },

            /**
             * @method join
             *
             * @param {string} separator 将数组形式的result.value连接为字符串形式时使用的分隔符，默认为空字符串''
             *
             * @desc 对当前解析器函数对象执行后的结果的value值，进行合并
             *
             */
            join: function(separator){
                var self = this;
                return Parser(function(stream, index){
                    var result = self.parse(stream, index);
                    if(result.success && result.value instanceof Array){
                        result.value = result.value.join(separator||'');
                    }

                    return result;
                });
            }
        }).initialize(f);
    }

    /**
     * 原子解析器的构造器，基于给定的模式（STR或RE），返回一个进行模式匹配（解析）的函数
     */
    return jObject.create({

        /**
         * @method string
         *
         * @param {string} str
         *
         * @return {function}
         *
         * @desc 基于一个给定的字符串，创建一个parse函数
         *
         */
        string: function(str){
            return Parser(function(stream, index){
                if(stream.substr(index, str.length) === str){
                    return success(index + str.length, str);
                }else{
                    return fail(index, str);
                }
            });
        },

        /**
         * @method regex
         *
         * @param {regex} re            正则表达式
         * @param {number} opt grp      捕获组，默认为0
         */
        regex: function(re, grp){
            grp = grp || 0;

            //对正则进行处理，加入^符号，从被截取的输入流开头进行匹配
            re = eval(re.toString().replace(/^\//, '/^'));
            return Parser(function(stream, index){
                var match = re.exec(stream.slice(index));

                if(match && match[grp]){
                    return success(index+match[0].length, match[grp]);
                }
                return fail(index, re);
            });
        },

        /**
         * @method success
         *
         * @param {string} value
         *
         * @desc 直接在输入流的当前位置返回一个成功状态
         *
         */
        success: function(value){
            return Parser(function(stream, index){
                return success(index, value);
            });
        },

        /**
         * @method fail
         *
         * @param {string} expected
         *
         * @desc 直接在当前输入流上返回一个失败状态
         *
         */
        fail: function(expected){
            return Parser(function(stream, index){
                return fail(index, expected);
            });
        },

        /**
         * @method chr
         *
         * @param {string} chr
         *
         * @desc 对当前输入流进行单个字符的匹配
         */
        chr: function(chr){
            return Parser(function(stream, index){
                if(stream[index] === chr){
                    return success(index+1, chr);
                }
                return fail(index, chr);
            });
        },

        /**
         * @method instr
         *
         * @param {string} str
         *
         * @desc 如果当前输入流中下一个字符在给定的string中，则返回成功状态
         *
         */
        inStr: function(str){
            return Parser(function(stream, index){
                if(str.indexOf(stream[index])>-1){
                    return success(index+1, stream[index]);
                }
                return fail(index, 'in ' + str);
            });
        },

        /**
         * @method noInStr
         *
         * @param str
         *
         * @desc 如果当前输入流下一个字符不在给定的字符串中，则返回成功状态
         */
        noInStr: function(str){
            return Parser(function(stream, index){
                if(str.indexOf(stream[index]) === -1){
                    return success(index+1, stream[index]);
                }
                return fail(index, 'no in '+ str);
            });
        },

        /**
         * @method until
         *
         * @param {function} assert
         *
         * @desc 不断的在输入流上进行匹配，直到不符合断言，将符合断言的串返回
         */
        until: function(assert){
            return Parser(function(stream, index){
                var values = [],
                chr;
                while(assert(stream[index])){
                    values.push(stream[index]);
                    index++;
                }
                if(values.length){
                    return success(index, values);
                }
                return fail(index, 'assert:' + assert.toString());
            });
        },

        /**
         * @method lazy
         *
         * @param {function} getParser
         *
         * @desc 解析规则由解析动作发生时才提供
         */
        lazy: function(getParser){

            return Parser(function(stream, index){
                var parser = getParser();
                return parser.parse(stream, index);
            });
        },

        /**
         * @method seq
         *
         * @param {Array:Parser} arguments      n个将要被以顺序方式组合的解析器
         *
         * @desc  进行解析器的顺序组合
         */
        seq: function(){
            var args = slice.call(arguments, 0);

            return Parser(function(stream, index){
                var currentIndex = index,
                values = [],
                result,
                parserIndex = 0,
                parser;
                while(parser = args[parserIndex++]){
                    result = parser.parse(stream, currentIndex);
                    if(result.success){
                        currentIndex = result.index;
                        values.push(result.value);
                    }else{
                        return fail(currentIndex, '');
                    }
                }
                return success(currentIndex, values);
            });
        },

        /**
         * @method or
         *
         * @param {Array:Parser} arguments        n个选择器，依次尝试匹配，返回第一个成功的
         *
         * @desc 进行解析器的或组合
         */
        or: function(){
            var args = slice.call(arguments, 0);

            return Parser(function(stream, index){
                var parser,
                parserIndex = 0;
                while(parser = args[parserIndex++]){
                    result = parser.parse(stream, index);
                    if(result.success){
                        return success(result.index, result.value);
                    }
                }
                return fail(index, 'in or_parser');
            });
        },

        /**
         * @method times
         *
         * @param {Parser} parser
         * @param {number} min
         * @param {number} max
         *
         * @desc 在当前输入流上，使用指定的parse进行最少min次，最多max次的匹配
         *
         */
        times: function(parser, min, max){
            return Parser(function(stream, index){
                var successTimes = 0,
                values = [];

                do{
                    result = parser.parse(stream, index);
                    if(result.success){
                        index = result.index;
                        successTimes++;
                        values.push(result.value);
                        if(successTimes === max){
                            break;
                        }
                    }
                }while(result.success);

                if(successTimes >= min && successTimes <= max){
                    return success(index, values);
                }else{
                    return fail(index, '');
                }
            });
        }

    });

    /**
     * @function success
     *
     * @param {number} index            匹配成功的位置
     * @param {string} value            匹配到的值
     */
    function success(index, value){
        return {
            success: true,
            index: index,
            value: value,
            expected: '',
            lastIndex: -1
        };
    }

    /**
     * @function fail
     *
     * @param {number} lastIndex        匹配失败的位置
     * @param {string} expected         期望匹配到的值
     */
    function fail(lastIndex, expected){
        return {
            success: false,
            index: -1,
            value: null,
            expected: expected,
            lastIndex: lastIndex
        };
    }
}());
<commit_msg>为parser解析函数对象增加.process方法，可以在解析结果上进行指定的处理<commit_after>/**
 *
 * jcon
 *
 * A JavaScript parser combinator Library
 *
 */
var jcon = (function(undefined){

    var slice = Array.prototype.slice;

    function Parser(f){

        return jFunction.create({
            /**
             * @method parse
             *
             */
            parse: function(){
                return this.__fun__.apply(this, arguments);
            },

            /**
             * @method seq
             *
             * @param {Array:Parser}
             *
             * @desc 使用this指向的当前解析器，和arguments中的解析器，进行连接运算，产生新的连接解析器
             *
             */
            seq: function(){
                var args = slice.call(arguments, 0);
                args.unshift(this);
                return jcon.seq.apply(jcon, args);
            },

            /**
             * @method or
             *
             * @param {Array:Parser}
             *
             * @desc 使用this指向的当前解析器，和arguments中的解析器，进行或运算，产生新的或解析器
             *
             */
            or: function(){
                var args = slice.call(arguments, 0);
                args.unshift(this);
                return jcon.or.apply(jcon, args);
            },

            /**
             *
             * @method times
             *
             * @param {number} min
             * @param {number} max
             *
             * @desc 返回this指向的当前parser的min到max次解析的解析器
             *
             */
            times: function(min, max){
                return jcon.times(this, min, max);
            },

            /**
             * @method process
             *
             * @param {function} proc
             *
             * @desc 对当前解析器函数对象的结果进行指定的处理
             *
             */
            process: function(proc){
                var self = this;
                return Parser(function(stream, index){
                    var result = self.parse(stream, index);
                    result = proc(result) || result;
                    return result;
                });
            },

            /**
             * @method join
             *
             * @param {string} separator 将数组形式的result.value连接为字符串形式时使用的分隔符，默认为空字符串''
             *
             * @desc 对当前解析器函数对象执行后的结果的value值，进行合并
             *
             */
            join: function(separator){

                separator = separator || '';
                return this.process(function(result){
                    if(!!result.success && result.value instanceof Array){
                        result.value = result.value.join(separator);
                    }
                });
            }

        }).initialize(f);
    }

    /**
     * 原子解析器的构造器，基于给定的模式（STR或RE），返回一个进行模式匹配（解析）的函数
     */
    return jObject.create({

        /**
         * @method string
         *
         * @param {string} str
         *
         * @return {function}
         *
         * @desc 基于一个给定的字符串，创建一个parse函数
         *
         */
        string: function(str){
            return Parser(function(stream, index){
                if(stream.substr(index, str.length) === str){
                    return success(index + str.length, str);
                }else{
                    return fail(index, str);
                }
            });
        },

        /**
         * @method regex
         *
         * @param {regex} re            正则表达式
         * @param {number} opt grp      捕获组，默认为0
         */
        regex: function(re, grp){
            grp = grp || 0;

            //对正则进行处理，加入^符号，从被截取的输入流开头进行匹配
            re = eval(re.toString().replace(/^\//, '/^'));
            return Parser(function(stream, index){
                var match = re.exec(stream.slice(index));

                if(match && match[grp]){
                    return success(index+match[0].length, match[grp]);
                }
                return fail(index, re);
            });
        },

        /**
         * @method success
         *
         * @param {string} value
         *
         * @desc 直接在输入流的当前位置返回一个成功状态
         *
         */
        success: function(value){
            return Parser(function(stream, index){
                return success(index, value);
            });
        },

        /**
         * @method fail
         *
         * @param {string} expected
         *
         * @desc 直接在当前输入流上返回一个失败状态
         *
         */
        fail: function(expected){
            return Parser(function(stream, index){
                return fail(index, expected);
            });
        },

        /**
         * @method chr
         *
         * @param {string} chr
         *
         * @desc 对当前输入流进行单个字符的匹配
         */
        chr: function(chr){
            return Parser(function(stream, index){
                if(stream[index] === chr){
                    return success(index+1, chr);
                }
                return fail(index, chr);
            });
        },

        /**
         * @method instr
         *
         * @param {string} str
         *
         * @desc 如果当前输入流中下一个字符在给定的string中，则返回成功状态
         *
         */
        inStr: function(str){
            return Parser(function(stream, index){
                if(str.indexOf(stream[index])>-1){
                    return success(index+1, stream[index]);
                }
                return fail(index, 'in ' + str);
            });
        },

        /**
         * @method noInStr
         *
         * @param str
         *
         * @desc 如果当前输入流下一个字符不在给定的字符串中，则返回成功状态
         */
        noInStr: function(str){
            return Parser(function(stream, index){
                if(str.indexOf(stream[index]) === -1){
                    return success(index+1, stream[index]);
                }
                return fail(index, 'no in '+ str);
            });
        },

        /**
         * @method until
         *
         * @param {function} assert
         *
         * @desc 不断的在输入流上进行匹配，直到不符合断言，将符合断言的串返回
         */
        until: function(assert){
            return Parser(function(stream, index){
                var values = [],
                chr;
                while(assert(stream[index])){
                    values.push(stream[index]);
                    index++;
                }
                if(values.length){
                    return success(index, values);
                }
                return fail(index, 'assert:' + assert.toString());
            });
        },

        /**
         * @method lazy
         *
         * @param {function} getParser
         *
         * @desc 解析规则由解析动作发生时才提供
         */
        lazy: function(getParser){

            return Parser(function(stream, index){
                var parser = getParser();
                return parser.parse(stream, index);
            });
        },

        /**
         * @method seq
         *
         * @param {Array:Parser} arguments      n个将要被以顺序方式组合的解析器
         *
         * @desc  进行解析器的顺序组合
         */
        seq: function(){
            var args = slice.call(arguments, 0);

            return Parser(function(stream, index){
                var currentIndex = index,
                values = [],
                result,
                parserIndex = 0,
                parser;
                while(parser = args[parserIndex++]){
                    result = parser.parse(stream, currentIndex);
                    if(result.success){
                        currentIndex = result.index;
                        values.push(result.value);
                    }else{
                        return fail(currentIndex, '');
                    }
                }
                return success(currentIndex, values);
            });
        },

        /**
         * @method or
         *
         * @param {Array:Parser} arguments        n个选择器，依次尝试匹配，返回第一个成功的
         *
         * @desc 进行解析器的或组合
         */
        or: function(){
            var args = slice.call(arguments, 0);

            return Parser(function(stream, index){
                var parser,
                parserIndex = 0;
                while(parser = args[parserIndex++]){
                    result = parser.parse(stream, index);
                    if(result.success){
                        return success(result.index, result.value);
                    }
                }
                return fail(index, 'in or_parser');
            });
        },

        /**
         * @method times
         *
         * @param {Parser} parser
         * @param {number} min
         * @param {number} max
         *
         * @desc 在当前输入流上，使用指定的parse进行最少min次，最多max次的匹配
         *
         */
        times: function(parser, min, max){
            return Parser(function(stream, index){
                var successTimes = 0,
                values = [];

                do{
                    result = parser.parse(stream, index);
                    if(result.success){
                        index = result.index;
                        successTimes++;
                        values.push(result.value);
                        if(successTimes === max){
                            break;
                        }
                    }
                }while(result.success);

                if(successTimes >= min && successTimes <= max){
                    return success(index, values);
                }else{
                    return fail(index, '');
                }
            });
        }

    });

    /**
     * @function success
     *
     * @param {number} index            匹配成功的位置
     * @param {string} value            匹配到的值
     */
    function success(index, value){
        return {
            success: true,
            index: index,
            value: value,
            expected: '',
            lastIndex: -1
        };
    }

    /**
     * @function fail
     *
     * @param {number} lastIndex        匹配失败的位置
     * @param {string} expected         期望匹配到的值
     */
    function fail(lastIndex, expected){
        return {
            success: false,
            index: -1,
            value: null,
            expected: expected,
            lastIndex: lastIndex
        };
    }
}());
<|endoftext|>


<commit_before>/* @flow */
import { randomBytes } from 'crypto'
import { ECPair, address as baddress, crypto as bcrypto } from 'bitcoinjs-lib'

export function getEntropy(numberOfBytes: string) {
  if (!numberOfBytes) {
    numberOfBytes = 32
  }
  return randomBytes(numberOfBytes)
}

export function makeECPrivateKey() {
  const keyPair = new ECPair.makeRandom({ rng: getEntropy })
  return keyPair.d.toBuffer(32).toString('hex')
}

export function publicKeyToAddress(publicKey: string) {
  const publicKeyBuffer = new Buffer(publicKey, 'hex')
  const publicKeyHash160 = bcrypto.hash160(publicKeyBuffer)
  const address = baddress.toBase58Check(publicKeyHash160, 0x00)
  return address
}
<commit_msg>testing flow works. fix intentional error<commit_after>/* @flow */
import { randomBytes } from 'crypto'
import { ECPair, address as baddress, crypto as bcrypto } from 'bitcoinjs-lib'

export function getEntropy(numberOfBytes: number) {
  if (!numberOfBytes) {
    numberOfBytes = 32
  }
  return randomBytes(numberOfBytes)
}

export function makeECPrivateKey() {
  const keyPair = new ECPair.makeRandom({ rng: getEntropy })
  return keyPair.d.toBuffer(32).toString('hex')
}

export function publicKeyToAddress(publicKey: string) {
  const publicKeyBuffer = new Buffer(publicKey, 'hex')
  const publicKeyHash160 = bcrypto.hash160(publicKeyBuffer)
  const address = baddress.toBase58Check(publicKeyHash160, 0x00)
  return address
}
<|endoftext|>