<commit_before>define(function () { 'use strict';

    function Emitter (obj) {
        if ( obj ) {
            Object.keys(Emitter.prototype).forEach(function (key) {
                if ( ! obj.hasOwnProperty(key) ) {
                    Object.defineProperty(obj, key, {
                        value: Emitter.prototype[key],
                        writable:true,
                        configurable:true
                    })
                }
            })
            return Emitter.call(obj)
        }
        // Using discriptor to prevent non-subTopic properties from being enumerable
        Object.defineProperties(this, {
            _callbacks : {
                value : {},
                writable : true
            }
        })
    }

    Emitter.prototype = {
        publish : function (topic, data) {
            var calls = this._callbacks
            if ( calls ) {
                calls = calls[topic]
                var i = calls.length
                while (i--) {
                    calls[i].call(calls[--i], data)
                }
            }
            return this
        },
        on : function (topics, callback, context) {
            var calls = this._callbacks || (this._callbacks = {})
            topics.split(/\s+/).forEach(function (topic) {
                calls[topic] = [context || this, callback].concat(calls[topic] || [])
            }, this)
            return this
        },
        once : function (topics, callback, context) {
            topics.split(/\s+/).forEach(function (topic) {
                var self = this
                function on (data) {
                    self.off(topic, on)
                    callback.call(context, data)
                }
                this.on(topic, callback, context)
            })
            return this
        },
        off : function (topics, callback) {
            var calls = this._callbacks
            if ( calls ) {
                if ( topics ) {
                    if ( callback ) {
                        topics.split(/\s+/).forEach(function (topic) {
                            var events = calls[topic]
                            if ( events ) {
                                events = events.slice()
                                var i = events.length
                                while (i--) {
                                    if (events[i--] === callback) {
                                        events.splice(i, 2)
                                        calls[topic] = events
                                        break
                                    }
                                }
                            }
                        })
                    } else {
                        topics.split(/\s+/).forEach(function (topic) {
                            delete calls[topic]
                        })
                    }
                } else {
                    this._callbacks = {}
                }
            }
            return this
        }
    }

    Object.defineProperty(Emitter.prototype, 'constructor', { value: Emitter })

    return Emitter
})<commit_msg>bug fix<commit_after>define(function () { 'use strict';

    function Emitter (obj) {
        if ( obj ) {
            Object.keys(Emitter.prototype).forEach(function (key) {
                if ( ! obj.hasOwnProperty(key) ) {
                    Object.defineProperty(obj, key, {
                        value: Emitter.prototype[key],
                        writable:true,
                        configurable:true
                    })
                }
            })
            return Emitter.call(obj)
        }
        // Using discriptor to prevent non-subTopic properties from being enumerable
        Object.defineProperties(this, {
            _callbacks : {
                value : {},
                writable : true
            }
        })
    }

    Emitter.prototype = {
        publish : function (topic, data) {
            var calls
            if ( calls = this._callbacks ) {
                calls = calls[topic]
                if (calls) {
                    var i = calls.length
                    while (i--) {
                        calls[i].call(calls[--i], data)
                    }
                }
            }
            return this
        },
        on : function (topics, callback, context) {
            var calls = this._callbacks || (this._callbacks = {})
            topics.split(/\s+/).forEach(function (topic) {
                calls[topic] = [context || this, callback].concat(calls[topic] || [])
            }, this)
            return this
        },
        once : function (topics, callback, context) {
            topics.split(/\s+/).forEach(function (topic) {
                var self = this
                function on (data) {
                    self.off(topic, on)
                    callback.call(context, data)
                }
                this.on(topic, callback, context)
            })
            return this
        },
        off : function (topics, callback) {
            var calls = this._callbacks
            if ( calls ) {
                if ( topics ) {
                    if ( callback ) {
                        topics.split(/\s+/).forEach(function (topic) {
                            var events = calls[topic]
                            if ( events ) {
                                events = events.slice()
                                var i = events.length
                                while (i--) {
                                    if (events[i--] === callback) {
                                        events.splice(i, 2)
                                        calls[topic] = events
                                        break
                                    }
                                }
                            }
                        })
                    } else {
                        topics.split(/\s+/).forEach(function (topic) {
                            delete calls[topic]
                        })
                    }
                } else {
                    this._callbacks = {}
                }
            }
            return this
        }
    }

    Object.defineProperty(Emitter.prototype, 'constructor', { value: Emitter })

    return Emitter
})<|endoftext|>


<commit_before>import Immutable from 'immutable'
import {
  EVENT_META,
  EVENT_META_TEXT,
  EVENT_MIDI_NOTE_ON,
  EVENT_MIDI_NOTE_OFF,
  createParser as createEventParser,
} from 'midievents'
import {
  PLAYING,
  PAUSED,
  STOPPED,
} from '../constants/playbackStates'
import {
  MIDI,
} from '../constants/resourceTypes'
import MIDIFile from 'midifile'
import MIDIPlayer from 'midiplayer'

export default class Player {
  constructor(actions) {
    this.ctx = null
    this.actions = actions
    this.tracks = new Map()
    this.midiPlayers = new Map()
    this._startTime = null
    this._endTimeout = null
  }

  update(state) {
    this.ctx = state.ctx
    const didSeek = this._startTime !== state.startTime
    this._startTime = state.startTime

    const isPlaying = state.state === PLAYING
    const tracks = state.tracks.get(state.song, Immutable.Map())

    // Clean up removed/replaced tracks.
    for (let [ trackKey, trackState ] of this.tracks) {
      const trackRemoved = !tracks.has(trackKey)
      const trackChanged = trackState.module !== tracks.get(trackKey).module
      if (!isPlaying || didSeek || trackRemoved || trackChanged) {
        this._removeTrack(trackKey)
      }
    }

    // Create new tracks.
    if (state.loaded) {
      for (let [ trackKey, track ] of tracks) {
        if (!this.tracks.has(trackKey) && track.fetched) {
          this.tracks.set(trackKey, this._createTrack(trackKey, state, track))
        }

        const trackState = this.tracks.get(trackKey)

        // Halt / resume analyzers.
        if (isPlaying) {
          trackState.analyzerNode.connect(this.ctx.destination)
        } else {
          trackState.analyzerNode.disconnect()
        }
      }
    }

    // Take stock of needed MIDI players.
    var usedMIDI = new Map()
    for (let [ trackKey, trackState ] of this.tracks) {
      for (let [ midiURL, ] of trackState.midis) {
        usedMIDI.set(midiURL, (usedMIDI.get(midiURL) || 0) + 1)
      }
    }

    // Create new MIDI players.
    let songDuration = 0
    for (let [ midiURL, ] of usedMIDI) {
      if (!this.midiPlayers.has(midiURL)) {
        const resource = state.resources.get(midiURL)
        if (!resource.data) {
          continue
        }
        let midiFile = new MIDIFile(resource.data)
        let midiPlayer = new MIDIPlayer({
          output: { send: this._handleMIDIEvent.bind(this, midiURL) },
        })
        midiPlayer.load(midiFile)
        this.midiPlayers.set(midiURL, midiPlayer)
      }
      const midiEvents = this.midiPlayers.get(midiURL).events
      const midiDuration = midiEvents[midiEvents.length - 1].playTime
      songDuration = Math.max(songDuration, midiDuration)
    }

    const now = performance.now()

    clearTimeout(this._endTimeout)
    if (state.loaded) {
      if (isPlaying) {
        const remaining = songDuration - (now - state.startTime)
        this._endTimeout = setTimeout(this.actions.playbackFinish, remaining)
      }

      // Unload disabled tracks after loading MIDI files so that songDuration is
      // calculated with full transport.
      for (let [ trackKey, track ] of tracks) {
        if (!track.enabled) {
          const trackState = this._removeTrack(trackKey)
          for (let [ midiURL, ] of trackState.midis) {
            usedMIDI.set(midiURL, usedMIDI.get(midiURL) - 1)
          }
        }
      }
    }

    this.timeOffset = now / 1000 - this.ctx.currentTime
    for (let [ midiURL, midiPlayer ] of this.midiPlayers) {
      if (usedMIDI.get(midiURL) <= 0) {
        // Remove unused MIDI players.
        midiPlayer.stop()
        this.midiPlayers.delete(midiURL)
      } else {
        // Synchronize MIDI player state.
        if (isPlaying && state.loaded) {
          if (midiPlayer.startTime !== state.startTime) {
            midiPlayer.stop()
            midiPlayer.play()
            midiPlayer.startTime = state.startTime
          }
        } else {
          midiPlayer.stop()
        }
      }
    }

    this.actions.playerUpdateFinish(songDuration)
  }

  _removeTrack(trackKey) {
    const trackState = this.tracks.get(trackKey)
    if (!trackState) {
      return
    }
    trackState.gainNode.disconnect()
    trackState.analyzerNode.disconnect()
    trackState.spyNode.disconnect()
    this.tracks.delete(trackKey)
    return trackState
  }

  _createTrack(trackKey, state, track) {
    const gainNode = this.ctx.createGain()
    gainNode.connect(this.ctx.destination)

    const analyzerNode = this.ctx.createScriptProcessor(0, 2, 2)
    analyzerNode.addEventListener('audioprocess', this._handleTrackAudio.bind(this, trackKey))
    analyzerNode.connect(this.ctx.destination)

    const spyNode = this.ctx.createGain()
    spyNode.connect(gainNode)
    spyNode.connect(analyzerNode)

    let trackState = {
      module: track.module,
      gainNode,
      analyzerNode,
      spyNode,
      midis: new Map(),
    }

    const trackTransport = {
      playMIDI(resource, onEvent) {
        if (!resource.type === MIDI) {
          throw new Error('playMIDI requires a resource of type MIDI')
        }
        trackState.midis.set(resource.url, onEvent)
      }
    }

    const trackResources = track.resources.map(res =>
      res.toMap().set('data', state.resources.get(res.url).data)
    ).toJS()

    track.module.create({
      transport: trackTransport,
      res: trackResources,
      ctx: this.ctx,
      out: spyNode,
    })

    return trackState
  }

  _handleMIDIEvent(midiURL, data, time) {
    // FIXME: work around midievents expecting more than one event.
    // Also 3rd and 7th arguments are placeholder times. Should pull req
    // midievents to make it easier to handle single events, or modify
    // midiplayer.
    data.splice(0, 0, 0, EVENT_META, EVENT_META_TEXT, 0, 0)
    const dataView = new DataView(new Uint8Array(data).buffer)
    const parser = createEventParser(dataView)
    parser.next()
    const ev = parser.next()
    delete ev.index
    delete ev.delta
    ev.time = time / 1000 - this.timeOffset
    ev.midi = {data, time}

    if (ev.time <= this.ctx.currentTime) {
      // Skip events in the past (due to seek, etc.)
      return
    }

    if (ev.type === EVENT_MIDI_NOTE_ON || ev.type === EVENT_MIDI_NOTE_OFF) {
      ev.note = ev.param1
      // https://en.wikipedia.org/wiki/MIDI_Tuning_Standard#Frequency_values
      ev.frequency = Math.pow(2, (ev.note - 69) / 12) * 440
    }

    for (let [trackKey, track] of this.tracks) {
      const subscription = track.midis.get(midiURL)
      if (subscription) {
        subscription(Object.assign({}, ev))
      }
    }
  }

  _handleTrackAudio(trackKey, ev) {
    const sampleCount = 100
    const levels = {}
    const buf = ev.inputBuffer
    for (let c = 0; c < buf.numberOfChannels; c++) {
      const data = buf.getChannelData(c)
      const step = Math.floor(data.length / sampleCount)
      let sum = 0
      let max = 0
      for (let i = 0; i < data.length; i += step) {
        sum += Math.abs(data[i])
        max = Math.max(max, data[i])
      }
      const avg = sum / sampleCount

      const channel = c === 0 ? 'left' : 'right'
      levels[channel + 'Avg'] = avg
      levels[channel + 'Max'] = max
      levels[channel + 'Clip'] = max > 1
    }

    this.actions.updateTrackLevels(trackKey, levels)
  }
}
<commit_msg>Fade tracks when removing before disconnecting<commit_after>import Immutable from 'immutable'
import {
  EVENT_META,
  EVENT_META_TEXT,
  EVENT_MIDI_NOTE_ON,
  EVENT_MIDI_NOTE_OFF,
  createParser as createEventParser,
} from 'midievents'
import {
  PLAYING,
  PAUSED,
  STOPPED,
} from '../constants/playbackStates'
import {
  MIDI,
} from '../constants/resourceTypes'
import MIDIFile from 'midifile'
import MIDIPlayer from 'midiplayer'

// Duration tracks fade out when removed (to avoid artifacts from immediate cuts)
const trackFadeTime = .02

export default class Player {
  constructor(actions) {
    this.ctx = null
    this.actions = actions
    this.tracks = new Map()
    this.midiPlayers = new Map()
    this._startTime = null
    this._endTimeout = null
  }

  update(state) {
    this.ctx = state.ctx
    const didSeek = this._startTime !== state.startTime
    this._startTime = state.startTime

    const isPlaying = state.state === PLAYING
    const tracks = state.tracks.get(state.song, Immutable.Map())

    // Clean up removed/replaced tracks.
    for (let [ trackKey, trackState ] of this.tracks) {
      const trackRemoved = !tracks.has(trackKey)
      const trackChanged = trackState.module !== tracks.get(trackKey).module
      if (!isPlaying || didSeek || trackRemoved || trackChanged) {
        this._removeTrack(trackKey)
      }
    }

    // Create new tracks.
    if (state.loaded) {
      for (let [ trackKey, track ] of tracks) {
        if (!this.tracks.has(trackKey) && track.fetched) {
          this.tracks.set(trackKey, this._createTrack(trackKey, state, track))
        }

        const trackState = this.tracks.get(trackKey)

        // Halt / resume analyzers.
        if (isPlaying) {
          trackState.analyzerNode.connect(this.ctx.destination)
        } else {
          trackState.analyzerNode.disconnect()
        }
      }
    }

    // Take stock of needed MIDI players.
    var usedMIDI = new Map()
    for (let [ trackKey, trackState ] of this.tracks) {
      for (let [ midiURL, ] of trackState.midis) {
        usedMIDI.set(midiURL, (usedMIDI.get(midiURL) || 0) + 1)
      }
    }

    // Create new MIDI players.
    let songDuration = 0
    for (let [ midiURL, ] of usedMIDI) {
      if (!this.midiPlayers.has(midiURL)) {
        const resource = state.resources.get(midiURL)
        if (!resource.data) {
          continue
        }
        let midiFile = new MIDIFile(resource.data)
        let midiPlayer = new MIDIPlayer({
          output: { send: this._handleMIDIEvent.bind(this, midiURL) },
        })
        midiPlayer.load(midiFile)
        this.midiPlayers.set(midiURL, midiPlayer)
      }
      const midiEvents = this.midiPlayers.get(midiURL).events
      const midiDuration = midiEvents[midiEvents.length - 1].playTime
      songDuration = Math.max(songDuration, midiDuration)
    }

    const now = performance.now()

    clearTimeout(this._endTimeout)
    if (state.loaded) {
      if (isPlaying) {
        const remaining = songDuration - (now - state.startTime)
        this._endTimeout = setTimeout(this.actions.playbackFinish, remaining)
      }

      // Unload disabled tracks after loading MIDI files so that songDuration is
      // calculated with full transport.
      for (let [ trackKey, track ] of tracks) {
        if (!track.enabled) {
          const trackState = this._removeTrack(trackKey)
          for (let [ midiURL, ] of trackState.midis) {
            usedMIDI.set(midiURL, usedMIDI.get(midiURL) - 1)
          }
        }
      }
    }

    this.timeOffset = now / 1000 - this.ctx.currentTime
    for (let [ midiURL, midiPlayer ] of this.midiPlayers) {
      if (usedMIDI.get(midiURL) <= 0) {
        // Remove unused MIDI players.
        midiPlayer.stop()
        this.midiPlayers.delete(midiURL)
      } else {
        // Synchronize MIDI player state.
        if (isPlaying && state.loaded) {
          if (midiPlayer.startTime !== state.startTime) {
            midiPlayer.stop()
            midiPlayer.play()
            midiPlayer.startTime = state.startTime
          }
        } else {
          midiPlayer.stop()
        }
      }
    }

    this.actions.playerUpdateFinish(songDuration)
  }

  _removeTrack(trackKey) {
    const trackState = this.tracks.get(trackKey)
    if (!trackState) {
      return
    }
    const ctxTime = this.ctx.currentTime
    const gain = trackState.gainNode.gain
    gain.cancelScheduledValues(ctxTime)
    gain.setValueAtTime(gain.value, ctxTime)
    gain.linearRampToValueAtTime(0, ctxTime + trackFadeTime)
    setTimeout(() => {
      trackState.gainNode.disconnect()
      trackState.analyzerNode.disconnect()
      trackState.spyNode.disconnect()
    }, trackFadeTime * 1000 + 100)  // 100ms slack between JS and ctx clocks.
    this.tracks.delete(trackKey)
    return trackState
  }

  _createTrack(trackKey, state, track) {
    const gainNode = this.ctx.createGain()
    gainNode.connect(this.ctx.destination)

    const analyzerNode = this.ctx.createScriptProcessor(0, 2, 2)
    analyzerNode.addEventListener('audioprocess', this._handleTrackAudio.bind(this, trackKey))
    analyzerNode.connect(this.ctx.destination)

    const spyNode = this.ctx.createGain()
    spyNode.connect(gainNode)
    spyNode.connect(analyzerNode)

    let trackState = {
      module: track.module,
      gainNode,
      analyzerNode,
      spyNode,
      midis: new Map(),
    }

    const trackTransport = {
      playMIDI(resource, onEvent) {
        if (!resource.type === MIDI) {
          throw new Error('playMIDI requires a resource of type MIDI')
        }
        trackState.midis.set(resource.url, onEvent)
      }
    }

    const trackResources = track.resources.map(res =>
      res.toMap().set('data', state.resources.get(res.url).data)
    ).toJS()

    track.module.create({
      transport: trackTransport,
      res: trackResources,
      ctx: this.ctx,
      out: spyNode,
    })

    return trackState
  }

  _handleMIDIEvent(midiURL, data, time) {
    // FIXME: work around midievents expecting more than one event.
    // Also 3rd and 7th arguments are placeholder times. Should pull req
    // midievents to make it easier to handle single events, or modify
    // midiplayer.
    data.splice(0, 0, 0, EVENT_META, EVENT_META_TEXT, 0, 0)
    const dataView = new DataView(new Uint8Array(data).buffer)
    const parser = createEventParser(dataView)
    parser.next()
    const ev = parser.next()
    delete ev.index
    delete ev.delta
    ev.time = time / 1000 - this.timeOffset
    ev.midi = {data, time}

    if (ev.time <= this.ctx.currentTime) {
      // Skip events in the past (due to seek, etc.)
      return
    }

    if (ev.type === EVENT_MIDI_NOTE_ON || ev.type === EVENT_MIDI_NOTE_OFF) {
      ev.note = ev.param1
      // https://en.wikipedia.org/wiki/MIDI_Tuning_Standard#Frequency_values
      ev.frequency = Math.pow(2, (ev.note - 69) / 12) * 440
    }

    for (let [trackKey, track] of this.tracks) {
      const subscription = track.midis.get(midiURL)
      if (subscription) {
        subscription(Object.assign({}, ev))
      }
    }
  }

  _handleTrackAudio(trackKey, ev) {
    const sampleCount = 100
    const levels = {}
    const buf = ev.inputBuffer
    for (let c = 0; c < buf.numberOfChannels; c++) {
      const data = buf.getChannelData(c)
      const step = Math.floor(data.length / sampleCount)
      let sum = 0
      let max = 0
      for (let i = 0; i < data.length; i += step) {
        sum += Math.abs(data[i])
        max = Math.max(max, data[i])
      }
      const avg = sum / sampleCount

      const channel = c === 0 ? 'left' : 'right'
      levels[channel + 'Avg'] = avg
      levels[channel + 'Max'] = max
      levels[channel + 'Clip'] = max > 1
    }

    this.actions.updateTrackLevels(trackKey, levels)
  }
}
<|endoftext|>


<commit_before>import fs                      from 'fs'
import minify                  from 'html-minify'
import { tidy as htmltidy }    from 'htmltidy'
import mjmlEngine              from './index'
import { version as VERSION }  from '../package.json'

const engine = mjmlEngine.mjml2html

/*
 * The version number is the NPM
 * version number. It should be the same as the MJML engine
 */
const version = () => VERSION

/*
 * Turns a callback style to a Promise style one
 */
const promisify = fn =>
  (...args) =>
    new Promise((resolve, reject) =>
      fn(...args.concat((err, ...data) =>
        err ? reject(err) : resolve(...data))))

/*
 * Minimal Error Handling
 */
const error   = (e) => {
  console.log(e.stack ? e.stack : e)
  process.exit(42)
}

/*
 * Utility functions
 * write: write to a file
 * pretty: prettify an html file
 * read: read a fileexists: ensure the file exists
 */
const write   = promisify(fs.writeFile)
const read    = promisify(fs.readFile)
const exists  = promisify((file, cb) => fs.access(file, fs.R_OK | fs.W_OK, cb))
const pretty  = (html) =>
  promisify(htmltidy)(html, { indent: true, wrap: 0, bare: true })

/*
 * Turns an MJML input file into a pretty HTML file
 * min: boolean that specify the output format (pretty/minified)
 */
const render = (input, { min, output }) => {
  exists(input)
    .then(()      => read(input))
    .then(mjml    => engine(mjml.toString()))
    .then(html    => min ? minify(html) : pretty(html))
    .then(result  => write(output, result))
    .catch(error)
}

/*
 * Watch changes on a specific input file by calling render on each change
 */
const watch = (input, options) =>
  fs.watch(input, (_, file) => render(input, options))

const capitalize = name => name.charAt(0).toUpperCase() + name.slice(1).toLowerCase().replace(/-/g, '')

/*
* Return the code of an MJML component for a given name
*/
const createComponent = (name, ending) => {
  const lowerName = name.toLowerCase()

return `
import React, { Component } from 'react'
import _ from 'loadash'
import {
  MJMLColumnElement,
  elements,
  registerElement,
} from 'mjml'

/*
 * Wrap your dependencies here.
 */
const {
  text: MjText,
} = elements;

const NAME = '${lowerName}'

@MJMLColumnElement({
  tagName: 'mj-${lowerName}',
  content: ' ',

  /*
   * These are your default css attributes
   */
  attributes: {
    'color': '#424242',
    'font-family': 'Helvetica',
    'margin-top': '10px'
  }
})
class ${name} extends Component {

  /*
   * Build your styling here
   */
  getStyles() {
    const { mjAttribute, color } = this.props

    return _.merge({}, this.constructor.baseStyles, {
      text: {
      /*
       * Get the color attribute
       * Example: <mj-${lowerName} color="blue">content</mj-${lowerName}>
       */
        color: mjAttribute('color')
      }
    })
  }

  render() {

    const css = this.getStyles(),
          content = 'Hello World!'

    return (
      <Mj${name} style={ css }>
        { content }
      </MjText>
    )
  }
}

export default ${name}
`
}

/*
 * Create a new component based on the default template
 */
const initComponent = (name, ending) =>
  write(`./${capitalize(name)}.js`, createComponent(capitalize(name), ending))
    .then(() => console.log(`Component created: ${capitalize(name)}`))

module.exports = {
  initComponent: initComponent,
  render: render,
  watch: watch,
  version: version
}
<commit_msg>register in component<commit_after>import fs                      from 'fs'
import minify                  from 'html-minify'
import { tidy as htmltidy }    from 'htmltidy'
import mjmlEngine              from './index'
import { version as VERSION }  from '../package.json'

const engine = mjmlEngine.mjml2html

/*
 * The version number is the NPM
 * version number. It should be the same as the MJML engine
 */
const version = () => VERSION

/*
 * Turns a callback style to a Promise style one
 */
const promisify = fn =>
  (...args) =>
    new Promise((resolve, reject) =>
      fn(...args.concat((err, ...data) =>
        err ? reject(err) : resolve(...data))))

/*
 * Minimal Error Handling
 */
const error   = (e) => {
  console.log(e.stack ? e.stack : e)
  process.exit(42)
}

/*
 * Utility functions
 * write: write to a file
 * pretty: prettify an html file
 * read: read a fileexists: ensure the file exists
 */
const write   = promisify(fs.writeFile)
const read    = promisify(fs.readFile)
const exists  = promisify((file, cb) => fs.access(file, fs.R_OK | fs.W_OK, cb))
const pretty  = (html) =>
  promisify(htmltidy)(html, { indent: true, wrap: 0, bare: true })

/*
 * Turns an MJML input file into a pretty HTML file
 * min: boolean that specify the output format (pretty/minified)
 */
const render = (input, { min, output }) => {
  exists(input)
    .then(()      => read(input))
    .then(mjml    => engine(mjml.toString()))
    .then(html    => min ? minify(html) : pretty(html))
    .then(result  => write(output, result))
    .catch(error)
}

/*
 * Watch changes on a specific input file by calling render on each change
 */
const watch = (input, options) =>
  fs.watch(input, (_, file) => render(input, options))

const capitalize = name => name.charAt(0).toUpperCase() + name.slice(1).toLowerCase().replace(/-/g, '')

/*
* Return the code of an MJML component for a given name
*/
const createComponent = (name, ending) => {
  const lowerName = name.toLowerCase()

return `
import React, { Component } from 'react'
import _ from 'loadash'
import {
  MJMLColumnElement,
  elements,
  registerElement,
} from 'mjml'

/*
 * Wrap your dependencies here.
 */
const {
  text: MjText,
} = elements;

const NAME = '${lowerName}'

@MJMLColumnElement({
  tagName: 'mj-${lowerName}',
  content: ' ',

  /*
   * These are your default css attributes
   */
  attributes: {
    'color': '#424242',
    'font-family': 'Helvetica',
    'margin-top': '10px'
  }
})
class ${name} extends Component {

  /*
   * Build your styling here
   */
  getStyles() {
    const { mjAttribute, color } = this.props

    return _.merge({}, this.constructor.baseStyles, {
      text: {
      /*
       * Get the color attribute
       * Example: <mj-${lowerName} color="blue">content</mj-${lowerName}>
       */
        color: mjAttribute('color')
      }
    })
  }

  render() {

    const css = this.getStyles(),
          content = 'Hello World!'

    return (
      <Mj${name} style={ css }>
        { content }
      </MjText>
    )
  }
}

registerElement('${lowerName}', ${name}${ending ? ', true' : ''})
export default ${name}
`
}

/*
 * Create a new component based on the default template
 */
const initComponent = (name, ending) =>
  write(`./${capitalize(name)}.js`, createComponent(capitalize(name), ending))
    .then(() => console.log(`Component created: ${capitalize(name)}`))

module.exports = {
  initComponent: initComponent,
  render: render,
  watch: watch,
  version: version
}
<|endoftext|>


<commit_before>/**
 * @file check-version
 * @author xiaowu
 * @email fe.xiaowu@gmail.com
 */

'use strict';

import Check from './index';

new Check();<commit_msg>开发命令行<commit_after>/**
 * @file check-version
 * @author xiaowu
 * @email fe.xiaowu@gmail.com
 */

'use strict';

import {readFileSync, existsSync} from 'fs';
import path from 'path';
import program from 'commander';

import pkg from '../package';
import Check from './index';
import {success, error} from './log';
import cache from './cache';

// 设置命令行工具
program
    .version(pkg.version)
    .option('-c, --config [filepath]', 'config file path')
    .parse(process.argv);

/**
 * 获取配置文件数据
 *
 * @return {Promise} 数据的Promise
 */
let getConfig = function () {
    return new Promise((resolve, reject) => {
        let configpath = cache.get('configpath');

        // 如果没有配置文件
        if (!configpath || 'string' !== typeof configpath) {
            return reject('请先使用【command -c /file/path】设置配置文件路径');
        }

        // 配置文件不存在
        if (!existsSync(configpath)) {
            return reject('配置文件不存在');
        }

        let config;

        // 解析json结构
        // 使用readfile可以保证每次都是新的
        try {
            config = readFileSync(configpath).toString();
            config = JSON.parse(config);
        }
        catch (e) {
            return reject(e.message);
        }

        resolve(config);
    });
};

/**
 * 设置文件配置
 *
 * @param {string} configpath 文件路径
 *
 * @return {Promise}
 */
let setConfig = function (configpath) {
    return new Promise((resolve, reject) => {
        // 路径设置有问题
        if (configpath === 'true') {
            return reject('please set the correct file path');
        }

        // 解析路径
        configpath = path.resolve('./', configpath);

        // 如果文件不存在
        if (!existsSync(configpath)) {
            return reject('config file does not exist');
        }

        // 设置缓存
        cache.set('configpath', configpath);

        resolve(configpath);
    });
};

// 如果是在配置文件
if (program.config) {
    setConfig(program.config).then(data => {
        success('config success : ' + data);
    }).catch(err => error(err));
}
else {
    getConfig().then(data => {
        new Check(data);
    }).catch(err => error(err));
}
<|endoftext|>


<commit_before>"use strict";

const dedent = require("dedent");
const isCI = require("is-ci");
const log = require("npmlog");
const yargs = require("yargs/yargs");
const globalOptions = require("./Command").builder;

module.exports = CLI;

/**
 * Essentially a factory that returns a yargs() instance that can
 * be used to call parse() immediately (as in ../bin/lerna) or by
 * unit tests to encapsulate instantiation with "real" arguments.
 *
 * @param {Array = []} argv
 * @param {String = process.cwd()} cwd
 */
function CLI(argv, cwd) {
  const cli = yargs(argv, cwd);

  // the options grouped under "Global Options:" header
  const globalKeys = Object.keys(globalOptions).concat(["help", "version"]);

  if (isCI || !process.stderr.isTTY) {
    log.disableColor();
    log.disableProgress();
  } else if (process.stderr.isTTY) {
    log.enableColor();
    log.enableUnicode();
    log.enableProgress();
  }

  return cli
    .usage("Usage: $0 <command> [options]")
    .options(globalOptions)
    .group(globalKeys, "Global Options:")
    .commandDir("./commands")
    .demandCommand(1, "A command is required. Pass --help to see all available commands and options.")
    .recommendCommands()
    .strict()
    .fail((msg, err) => {
      // certain yargs validations throw strings :P
      const actual = err || new Error(msg);

      // ValidationErrors are already logged
      if (actual.name !== "ValidationError") {
        // the recommendCommands() message is too terse
        if (/Did you mean/.test(actual.message)) {
          log.error("lerna", `Unknown command "${cli.parsed.argv._[0]}"`);
        }
        log.error("lerna", actual.message);
      }

      // exit non-zero so the CLI can be usefully chained
      process.exitCode = 1;
    })
    .alias("h", "help")
    .alias("v", "version")
    .wrap(cli.terminalWidth()).epilogue(dedent`
      When a command fails, all logs are written to lerna-debug.log in the current working directory.

      For more information, find our manual at https://github.com/lerna/lerna
    `);
}
<commit_msg>Disable all non-error logging when stdout is piped (#1300)<commit_after>"use strict";

const dedent = require("dedent");
const isCI = require("is-ci");
const log = require("npmlog");
const yargs = require("yargs/yargs");
const globalOptions = require("./Command").builder;

module.exports = CLI;

/**
 * Essentially a factory that returns a yargs() instance that can
 * be used to call parse() immediately (as in ../bin/lerna) or by
 * unit tests to encapsulate instantiation with "real" arguments.
 *
 * @param {Array = []} argv
 * @param {String = process.cwd()} cwd
 */
function CLI(argv, cwd) {
  const cli = yargs(argv, cwd);

  // the options grouped under "Global Options:" header
  const globalKeys = Object.keys(globalOptions).concat(["help", "version"]);

  if (isCI || !process.stderr.isTTY) {
    log.disableColor();
    log.disableProgress();
  } else if (!process.stdout.isTTY) {
    // stdout is being piped, don't log non-errors or progress bars
    log.disableProgress();

    cli.check(parsedArgv => {
      // eslint-disable-next-line no-param-reassign
      parsedArgv.loglevel = "error";

      // return truthy or else it blows up
      return parsedArgv;
    });
  } else if (process.stderr.isTTY) {
    log.enableColor();
    log.enableUnicode();
    log.enableProgress();
  }

  return cli
    .usage("Usage: $0 <command> [options]")
    .options(globalOptions)
    .group(globalKeys, "Global Options:")
    .commandDir("./commands")
    .demandCommand(1, "A command is required. Pass --help to see all available commands and options.")
    .recommendCommands()
    .strict()
    .fail((msg, err) => {
      // certain yargs validations throw strings :P
      const actual = err || new Error(msg);

      // ValidationErrors are already logged
      if (actual.name !== "ValidationError") {
        // the recommendCommands() message is too terse
        if (/Did you mean/.test(actual.message)) {
          log.error("lerna", `Unknown command "${cli.parsed.argv._[0]}"`);
        }
        log.error("lerna", actual.message);
      }

      // exit non-zero so the CLI can be usefully chained
      process.exitCode = 1;
    })
    .alias("h", "help")
    .alias("v", "version")
    .wrap(cli.terminalWidth()).epilogue(dedent`
      When a command fails, all logs are written to lerna-debug.log in the current working directory.

      For more information, find our manual at https://github.com/lerna/lerna
    `);
}
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import Lightbox from 'react-images';
import Image from './Image.js';

var update = require('react-addons-update');

class Gallery extends Component {
    constructor (props) {
        super(props);

        this.state = {
            lightboxIsOpen: this.props.isOpen,
            selectedImages: this.props.selectedImages,
            currentImage: this.props.currentImage,
            containerWidth: 0
        };

        this.handleResize = this.handleResize.bind(this);
        this.closeLightbox = this.closeLightbox.bind(this);
        this.gotoNext = this.gotoNext.bind(this);
        this.gotoPrevious = this.gotoPrevious.bind(this);
        this.handleClickImage = this.handleClickImage.bind(this);
        this.openLightbox = this.openLightbox.bind(this);
        this.onToggleSelected = this.onToggleSelected.bind(this);
    }

    componentDidMount () {
        this.setState(
            {containerWidth:
             Math.floor(ReactDOM.findDOMNode(this).clientWidth)});
        window.addEventListener('resize', this.handleResize);
    }

    componentWillUpdate (np, ns) {
        if(this.state.selectedImages != ns.selectedImages){
            if(this.props.onSelectedImagesChange)
                this.props.onSelectedImagesChange(ns.selectedImages);
        }
    }

    componentDidUpdate () {
        if (ReactDOM.findDOMNode(this).clientWidth
            !== this.state.containerWidth){
            this.setState(
                {containerWidth:
                 Math.floor(ReactDOM.findDOMNode(this).clientWidth)});
        }
    }

    handleResize (e) {
        this.setState(
            {containerWidth:
             Math.floor(ReactDOM.findDOMNode(this).clientWidth)});
    }

    openLightbox (index, event) {
        event.preventDefault();
        this.setState({
            currentImage: index,
            lightboxIsOpen: true
        });
    }

    closeLightbox () {
        this.setState({
            currentImage: 0,
            lightboxIsOpen: false
        });
    }

    gotoPrevious () {
        this.setState({
            currentImage: this.state.currentImage - 1
        });
    }

    gotoNext () {
        this.setState({
            currentImage: this.state.currentImage + 1
        });
    }

    handleClickImage () {
        if (this.state.currentImage === this.props.images.length - 1) return;
        this.gotoNext();
    }

    onToggleSelected (idx, isSelected) {
        if(isSelected){
            if(this.state.selectedImages.indexOf(idx) === -1){
                this.setState({selectedImages:
                               update(this.state.selectedImages,
                                      {$push: [idx]})});
            }
        }
        else {
            var i = this.state.selectedImages.indexOf(idx);
            if(i > -1){
                this.setState({
                    selectedImages: update(this.state.selectedImages,
                                           {$splice: [[i, 1]]})});
            }
        }
    }

    /**
     * Distribute a delta (integer value) to n items based on
     * the size (width) of the items thumbnails.
     */
    calculateCutOff (len, delta, items) {
        // resulting distribution
        var cutoff = [];
        var cutsum = 0;

        // distribute the delta based on the proportion of
        // thumbnail size to length of all thumbnails.
        for(var i in items) {
            var item = items[i];
            var fractOfLen = item.scaletwidth / len;
            cutoff[i] = Math.floor(fractOfLen * delta);
            cutsum += cutoff[i];
        }

        // still more pixel to distribute because of decimal
        // fractions that were omitted.
        var stillToCutOff = delta - cutsum;
        while(stillToCutOff > 0) {
            for(i in cutoff) {
                // distribute pixels evenly until done
                cutoff[i]++;
                cutsum++; //debug
                stillToCutOff--;
                if (stillToCutOff < 0) break;
            }
        }
        return cutoff;
    }

    /**
     * Takes images from the items array (removes them) as
     * long as they fit into a width of maxwidth pixels.
     */
    buildImageRow (items) {
        var row = [];
        var len = 0;

        // left and right margin = 2x props.margin
        var imgMargin = 2 * this.props.margin;

        // Build a row of images until longer than maxwidth
        while(items.length > 0 && len < this.state.containerWidth) {
            var item = items.shift();
            row.push(item);
            len += (item.scaletwidth + imgMargin);
        }

        // calculate by how many pixels too long...
        var delta = len - this.state.containerWidth;

        // if the line is too long, make images smaller
        if(row.length > 0 && delta > 0) {

            // calculate the distribution to each image in the row
            var cutoff = this.calculateCutOff(len, delta, row);

            for(var i in row) {
                var pixelsToRemove = cutoff[i];
                item = row[i];

                // move the left border inwards by half the pixels
                item.marginLeft = -Math.abs(Math.floor(pixelsToRemove / 2));

                // shrink the width of the image by pixelsToRemove
                item.vwidth = item.scaletwidth - pixelsToRemove;
            }
        }
        else {
            // all images fit in the row, set vx and vwidth
            for(var i in row) {
                item = row[i];
                item.marginLeft = 0;
                item.vwidth = item.scaletwidth;
            }
        }
        return row;
    }

    /**
     * Scales thumbnails to match props.rowHeight
     */
    scaleThumbs (items) {
        for (var i in items) {
            items[i].scaletwidth =
                Math.floor(this.props.rowHeight *
                           (items[i].thumbnailWidth / items[i].thumbnailHeight));
        }
        return items;
    }

    /**
     * Builds images and packs them in rows
     */
    renderGallery () {
        if (!this.props.images) return;
        if (this.state.containerWidth == 0) return;

        // Calculate new thumbnail size to match this.props.rowHeight
        var items = this.scaleThumbs(this.props.images.slice());

        // calculate rows of images
        var images = [];
        var rows = [];
        while(items.length > 0) {
            rows.push(this.buildImageRow(items));
        }

        var idx = 0;
        for(var r in rows) {
            for(var i in rows[r]) {
                var item = rows[r][i];
                // create image
                images.push(
                        <Image
                    key={"Image-"+idx}
                    item={item}
                    index={idx}
                    margin={this.props.margin}
                    height={this.props.rowHeight}
                    isSelectable={this.props.enableImageSelection}
                    onClick={this.openLightbox}
                    onToggleSelected={this.onToggleSelected}/>
                );
                idx++;
            }
        }
        return images;
    }

    render () {
        return (

                {this.renderGallery()}
                <Lightbox
            images={this.props.images}
            backdropClosesModal={this.props.backdropClosesModal}
            currentImage={this.state.currentImage}
            customControls={this.props.customControls}
            enableKeyboardInput={this.props.enableKeyboardInput}
            imageCountSeparator={this.props.imageCountSeparator}
            isOpen={this.state.lightboxIsOpen}
            onClickImage={this.handleClickImage}
            onClickNext={this.gotoNext}
            onClickPrev={this.gotoPrevious}
            onClose={this.closeLightbox}
            showCloseButton={this.props.showCloseButton}
            showImageCount={this.props.showImageCount}
                />

        );
    }
};

Gallery.displayName = 'Gallery';

Gallery.propTypes = {
    images: PropTypes.arrayOf(
        PropTypes.shape({
            src: PropTypes.string.isRequired,
            thumbnail: PropTypes.string.isRequired,
            srcset: PropTypes.array,
            caption: PropTypes.string,
            thumbnailWidth: PropTypes.number,
            thumbnailHeight: PropTypes.number
        })
    ).isRequired,
    enableImageSelection: PropTypes.bool,
    selectedImages: PropTypes.arrayOf(PropTypes.number),
    onSelectedImagesChange: PropTypes.func,
    rowHeight: PropTypes.number,
    margin: PropTypes.number, // margin size for each image
    backdropClosesModal: PropTypes.bool,
    currentImage: PropTypes.number,
    customControls: PropTypes.arrayOf(PropTypes.node),
    enableKeyboardInput: PropTypes.bool,
    imageCountSeparator: PropTypes.string,
    isOpen: PropTypes.bool,
    onClickImage: PropTypes.func,
    onClickNext: PropTypes.func,
    onClickPrev: PropTypes.func,
    onClose: PropTypes.func.isRequired,
    showCloseButton: PropTypes.bool,
    showImageCount: PropTypes.bool
};

Gallery.defaultProps = {
    enableImageSelection: true,
    selectedImages: [],
    rowHeight: 160,
    margin: 2,
    backdropClosesModal: false,
    currentImage: 0,
    enableKeyboardInput: true,
    imageCountSeparator: ' of ',
    isOpen: false,
    showCloseButton: true,
    showImageCount: true
};

module.exports = Gallery;
<commit_msg>drives all ownee state, other than hover<commit_after>import React, { Component, PropTypes } from 'react';
import Lightbox from 'react-images';
import Image from './Image.js';

var update = require('react-addons-update');

class Gallery extends Component {
    constructor (props) {
        super(props);

        this.state = {
            lightboxIsOpen: this.props.isOpen,
            selectedImages: this.props.selectedImages,
            currentImage: this.props.currentImage,
            containerWidth: 0
        };

        this.handleResize = this.handleResize.bind(this);
        this.closeLightbox = this.closeLightbox.bind(this);
        this.gotoNext = this.gotoNext.bind(this);
        this.gotoPrevious = this.gotoPrevious.bind(this);
        this.handleClickImage = this.handleClickImage.bind(this);
        this.openLightbox = this.openLightbox.bind(this);
        this.onToggleSelected = this.onToggleSelected.bind(this);
    }

    componentDidMount () {
        this.setState(
            {containerWidth:
             Math.floor(ReactDOM.findDOMNode(this).clientWidth)});
        window.addEventListener('resize', this.handleResize);
    }

    componentWillUpdate (np, ns) {
        if(this.state.selectedImages != ns.selectedImages){
            if(this.props.onSelectedImagesChange)
                this.props.onSelectedImagesChange(ns.selectedImages);
        }
    }

    componentDidUpdate () {
        if (ReactDOM.findDOMNode(this).clientWidth
            !== this.state.containerWidth){
            this.setState(
                {containerWidth:
                 Math.floor(ReactDOM.findDOMNode(this).clientWidth)});
        }
    }

    handleResize (e) {
        this.setState(
            {containerWidth:
             Math.floor(ReactDOM.findDOMNode(this).clientWidth)});
    }

    openLightbox (index, event) {
        event.preventDefault();
        this.setState({
            currentImage: index,
            lightboxIsOpen: true
        });
    }

    closeLightbox () {
        this.setState({
            currentImage: 0,
            lightboxIsOpen: false
        });
    }

    gotoPrevious () {
        this.setState({
            currentImage: this.state.currentImage - 1
        });
    }

    gotoNext () {
        this.setState({
            currentImage: this.state.currentImage + 1
        });
    }

    handleClickImage () {
        if (this.state.currentImage === this.props.images.length - 1) return;
        this.gotoNext();
    }

    onToggleSelected (index, event) {
        event.preventDefault();
        var i = this.state.selectedImages.indexOf(index);
        if(i == -1){
            this.setState({selectedImages:
                           update(this.state.selectedImages,
                                  {$push: [index]})});
        }
        else {
            this.setState({
                selectedImages: update(this.state.selectedImages,
                                       {$splice: [[i, 1]]})});
        }
    }

    /**
     * Distribute a delta (integer value) to n items based on
     * the size (width) of the items thumbnails.
     */
    calculateCutOff (len, delta, items) {
        // resulting distribution
        var cutoff = [];
        var cutsum = 0;

        // distribute the delta based on the proportion of
        // thumbnail size to length of all thumbnails.
        for(var i in items) {
            var item = items[i];
            var fractOfLen = item.scaletwidth / len;
            cutoff[i] = Math.floor(fractOfLen * delta);
            cutsum += cutoff[i];
        }

        // still more pixel to distribute because of decimal
        // fractions that were omitted.
        var stillToCutOff = delta - cutsum;
        while(stillToCutOff > 0) {
            for(i in cutoff) {
                // distribute pixels evenly until done
                cutoff[i]++;
                cutsum++; //debug
                stillToCutOff--;
                if (stillToCutOff < 0) break;
            }
        }
        return cutoff;
    }

    /**
     * Takes images from the items array (removes them) as
     * long as they fit into a width of maxwidth pixels.
     */
    buildImageRow (items) {
        var row = [];
        var len = 0;

        // left and right margin = 2x props.margin
        var imgMargin = 2 * this.props.margin;

        // Build a row of images until longer than maxwidth
        while(items.length > 0 && len < this.state.containerWidth) {
            var item = items.shift();
            row.push(item);
            len += (item.scaletwidth + imgMargin);
        }

        // calculate by how many pixels too long...
        var delta = len - this.state.containerWidth;

        // if the line is too long, make images smaller
        if(row.length > 0 && delta > 0) {

            // calculate the distribution to each image in the row
            var cutoff = this.calculateCutOff(len, delta, row);

            for(var i in row) {
                var pixelsToRemove = cutoff[i];
                item = row[i];

                // move the left border inwards by half the pixels
                item.marginLeft = -Math.abs(Math.floor(pixelsToRemove / 2));

                // shrink the width of the image by pixelsToRemove
                item.vwidth = item.scaletwidth - pixelsToRemove;
            }
        }
        else {
            // all images fit in the row, set vx and vwidth
            for(var i in row) {
                item = row[i];
                item.marginLeft = 0;
                item.vwidth = item.scaletwidth;
            }
        }
        return row;
    }

    /**
     * Scales thumbnails to match props.rowHeight
     */
    scaleThumbs (items) {
        for (var i in items) {
            items[i].scaletwidth =
                Math.floor(this.props.rowHeight *
                           (items[i].thumbnailWidth / items[i].thumbnailHeight));
        }
        return items;
    }

    isImageSelected (idx) {
        if (this.state.selectedImages.indexOf(idx) > -1)
            return true;
        return false;
    }

    /**
     * Builds images and packs them in rows
     */
    renderGallery () {
        if (!this.props.images) return;
        if (this.state.containerWidth == 0) return;

        // Calculate new thumbnail size to match this.props.rowHeight
        var items = this.scaleThumbs(this.props.images.slice());

        // calculate rows of images
        var images = [];
        var rows = [];
        while(items.length > 0) {
            rows.push(this.buildImageRow(items));
        }

        var idx = 0;
        for(var r in rows) {
            for(var i in rows[r]) {
                var item = rows[r][i];
                // create image
                images.push(
                        <Image
                    key={"Image-"+idx}
                    item={item}
                    index={idx}
                    margin={this.props.margin}
                    height={this.props.rowHeight}
                    isSelectable={this.props.enableImageSelection}
                    isSelected={this.isImageSelected(idx)}
                    onClick={this.openLightbox}
                    onToggleSelected={this.onToggleSelected}/>
                );
                idx++;
            }
        }
        return images;
    }

    render () {
        return (

                {this.renderGallery()}
                <Lightbox
            images={this.props.images}
            backdropClosesModal={this.props.backdropClosesModal}
            currentImage={this.state.currentImage}
            customControls={this.props.customControls}
            enableKeyboardInput={this.props.enableKeyboardInput}
            imageCountSeparator={this.props.imageCountSeparator}
            isOpen={this.state.lightboxIsOpen}
            onClickImage={this.handleClickImage}
            onClickNext={this.gotoNext}
            onClickPrev={this.gotoPrevious}
            onClose={this.closeLightbox}
            showCloseButton={this.props.showCloseButton}
            showImageCount={this.props.showImageCount}
                />

        );
    }
};

Gallery.displayName = 'Gallery';

Gallery.propTypes = {
    images: PropTypes.arrayOf(
        PropTypes.shape({
            src: PropTypes.string.isRequired,
            thumbnail: PropTypes.string.isRequired,
            srcset: PropTypes.array,
            caption: PropTypes.string,
            thumbnailWidth: PropTypes.number,
            thumbnailHeight: PropTypes.number
        })
    ).isRequired,
    enableImageSelection: PropTypes.bool,
    selectedImages: PropTypes.arrayOf(PropTypes.number),
    onSelectedImagesChange: PropTypes.func,
    rowHeight: PropTypes.number,
    margin: PropTypes.number, // margin size for each image
    backdropClosesModal: PropTypes.bool,
    currentImage: PropTypes.number,
    customControls: PropTypes.arrayOf(PropTypes.node),
    enableKeyboardInput: PropTypes.bool,
    imageCountSeparator: PropTypes.string,
    isOpen: PropTypes.bool,
    onClickImage: PropTypes.func,
    onClickNext: PropTypes.func,
    onClickPrev: PropTypes.func,
    onClose: PropTypes.func.isRequired,
    showCloseButton: PropTypes.bool,
    showImageCount: PropTypes.bool
};

Gallery.defaultProps = {
    enableImageSelection: true,
    selectedImages: [],
    rowHeight: 180,
    margin: 2,
    backdropClosesModal: false,
    currentImage: 0,
    enableKeyboardInput: true,
    imageCountSeparator: ' of ',
    isOpen: false,
    showCloseButton: true,
    showImageCount: true
};

module.exports = Gallery;
<|endoftext|>


<commit_before>var currentNumber = 1;
var lastFibonacci = "0";
var currentFibonacci = "1";
var endingString = "aaa";

function getNextFib()
{
	currentNumber++;
	var oldLastFibonacci = lastFibonacci;
	lastFibonacci = currentFibonacci;
	return currentFibonacci = currentFibonacci.add(oldLastFibonacci);
}

function getNextFibUI()
{
	var nextVal = getNextFib();
	$("#currentNumber").text( currentNumber );
	$("#currentVal").text( nextVal );
	window.scrollTo(0, 0);
}

function clearScore()
{
	currentNumber = 1;
	lastFibonacci = "0";
	currentFibonacci = "1";
	endingString = "aaa";
	updateUI();
}

function updateUI()
{
	$("#currentNumber").text( currentNumber );
	$("#currentVal").text( currentFibonacci );
	window.scrollTo(0, 0);
}

String.prototype.endsWith = function(suffix) {
    return this.indexOf(suffix, this.length - suffix.length) !== -1;
};

function getPaddingString(length)
{
	var string = "";

	for(var i = 0; i < length; i++)
	{
		string += "0";
	}

	return string;
}

String.prototype.add = function(number){
	var thisLastDigit = this.length;
	var thatLastDigit = number.length;
	var carried = 0;
	var finalString = "";

	var tempThis = "0" + this;
	number = "0" + number;

	var padding = thisLastDigit - thatLastDigit;

	var paddingString = getPaddingString(Math.abs(padding));

	if(padding > 0)
	{
		number = paddingString + number;
	}
	else
	{
		tempThis = paddingString + tempThis;
	}

	for(var i = Math.min(thisLastDigit, thatLastDigit) + Math.abs(padding); i > -1; i--)
	{
		var newNum = tempThis.charCodeAt(i) + number.charCodeAt(i) + carried - 96;
		if(newNum >= 10)
		{
			carried = ( newNum - (newNum % 10) ) / 10;
			newNum = newNum % 10;
		}
		else
		{
			carried = 0;
		}

		finalString = newNum + finalString + "";
	}

	if(finalString[0] == "0"){ finalString = finalString.substr(1); }

	return finalString;
};

function correctString(type, aimString)
{
	if(type == "ends"){ return (currentFibonacci).endsWith( aimString ); }
	else if(type == "contains"){ return (currentFibonacci.indexOf(aimString) != -1 );}
	else{
		return false;
	}
}

function getNext10000FibsUI(type)
{
	endingString = $("#ending").val();
	for(var i = 0; i < 9998 ; i ++)
	{
		getNextFib();
		if( correctString(type, endingString) ){
			updateUI();
			return;
		}
	}
	getNextFibUI();
}

function getNextHundredThousandFibsUI(type)
{
	endingString = $("#ending").val();
	for(var i = 0; i < 99998 ; i ++)
	{
		getNextFib();
		if( correctString(type, endingString) ){
			updateUI();
			return;
		}
	}
	getNextFibUI();
}

function getNthFib(n)
{

}
<commit_msg>Update script.js<commit_after>var currentNumber = 1;
var lastFibonacci = "0";
var currentFibonacci = "1";
var endingString = "aaa";

function getNextFib()
{
	currentNumber++;
	var oldLastFibonacci = lastFibonacci;
	lastFibonacci = currentFibonacci;
	return currentFibonacci = currentFibonacci.add(oldLastFibonacci);
}

function getNextFibUI()
{
	var nextVal = getNextFib();
	$("#currentNumber").text( currentNumber );
	$("#currentVal").text( nextVal );
	window.scrollTo(0, 0);
}

function clearScore()
{
	currentNumber = 1;
	lastFibonacci = "0";
	currentFibonacci = "1";
	endingString = "aaa";
	updateUI();
}

function updateUI()
{
	$("#currentNumber").text( currentNumber );
	$("#currentVal").text( currentFibonacci );
	window.scrollTo(0, 0);
}

String.prototype.endsWith = function(suffix) {
    return this.indexOf(suffix, this.length - suffix.length) !== -1;
};

function getPaddingString(length)
{
	var string = "";

	for(var i = 0; i < length; i++)
	{
		string += "0";
	}

	return string;
}

String.prototype.add = function(number){
	var thisLastDigit = this.length;
	var thatLastDigit = number.length;
	var carried = 0;
	var finalString = "";

	var tempThis = "0" + this;
	number = "0" + number;

	var padding = thisLastDigit - thatLastDigit;

	var paddingString = getPaddingString(Math.abs(padding));

	if(padding > 0)
	{
		number = paddingString + number;
	}
	else
	{
		tempThis = paddingString + tempThis;
	}

	for(var i = Math.min(thisLastDigit, thatLastDigit) + Math.abs(padding); i > -1; i--)
	{
		var newNum = tempThis.charCodeAt(i) + number.charCodeAt(i) + carried - 96;
		if(newNum >= 10)
		{
			carried = ( newNum - (newNum % 10) ) / 10;
			newNum = newNum % 10;
		}
		else
		{
			carried = 0;
		}

		finalString = newNum + finalString + "";
	}

	if(finalString[0] == "0"){ finalString = finalString.substr(1); }

	return finalString;
};

function correctString(type, aimString)
{
	if(type == "ends"){ return (currentFibonacci).endsWith( aimString ); }
	else if(type == "contains"){ return (currentFibonacci.indexOf(aimString) != -1 );}
	else{
		return false;
	}
}

function getNext10000FibsUI(type)
{
	endingString = $("#ending").val();
	for(var i = 0; i < 9999 ; i ++)
	{
		getNextFib();
		if( correctString(type, endingString) ){
			updateUI();
			return;
		}
	}
	getNextFibUI();
}

function getNextHundredThousandFibsUI(type)
{
	endingString = $("#ending").val();
	for(var i = 0; i < 99999 ; i ++)
	{
		getNextFib();
		if( correctString(type, endingString) ){
			updateUI();
			return;
		}
	}
	getNextFibUI();
}

function getNthFib(n)
{

}
<|endoftext|>


<commit_before>function read(){
	var a = document.getElementById("a").value;
	var b = document.getElementById("b").value;
	var c = document.getElementById("c").value;

	var coef=[a,b,c];

	return coef;
}

function solveDelta(coef){
	var deltaa=coef[1]*coef[1] - 4*coef[0]*coef[2];
	return deltaa;

}

function solveRoots(coef,delta){
	var x1=x2=x1im=x2im=0;
	if(delta==0){
		x1=(-coef[1])/(2*coef[0]);
		x2=(-coef[1])/(2*coef[0]);
	}
	else if(delta<0) {
		x1=(-coef[1])/2*coef[0];
		x1im=Math.sqrt(-delta)/2*coef[0];
		x2=(-coef[1])/2*coef[0];
		x2im=-Math.sqrt(-delta)/2*coef[0];
		// document.getElementById("x1").innerHTML =x1.toString()+"+"+x1im.toString()+"i";
		// document.getElementById("x2").innerHTML =x2.toString()+x2im.toString()+"i";
	}
	else if(delta>0){
		x1 = ((-coef[1])+Math.sqrt(delta))/(2*coef[0]);
		x2 = ((-coef[1])-Math.sqrt(delta))/(2*coef[0]);
		// document.getElementById("x1").innerHTML = "x1 =" + x1;
		// document.getElementById("x2").innerHTML = "x2 =" + x2;
	}
	var radacini=[x1,x2,x1im,x2im];
	return radacini;
}

function showAnswer(radacini){

	document.getElementById("x1").innerHTML = "x1 =" + radacini[0] + "+" + radacini[2] + "i";
	document.getElementById("x2").innerHTML = "x2 =" + radacini[1] + radacini[3] + "i";
}

function solve(){
			x1=x2=x1im=x2im=0;
			var coef = read();
			var deltaa = solveDelta(coef);
			var radacini=solveRoots(coef,deltaa);

			// document.getElementById("delta").innerHTML = "Delta=" + delta;
			showAnswer(radacini);
			document.getElementById("delta").innerHTML = "Delta=" + deltaa;
			document.getElementById("aa").innerHTML = "a= " + coef[0];
			document.getElementById("bb").innerHTML = "b= " + coef[1];
			document.getElementById("cc").innerHTML = "c= " + coef[2];

		}
<commit_msg>Split functions.<commit_after>function read(){
	var a = document.getElementById("a").value;
	var b = document.getElementById("b").value;
	var c = document.getElementById("c").value;

	var coef=[a,b,c];

	return coef;
}

function solveDelta(coef){
	var delta=coef[1]*coef[1] - 4*coef[0]*coef[2];
	return delta;

}

function solveRoots(coef,delta){
	var x1=x2=x1im=x2im=0;
	if(delta==0){
		x1=(-coef[1])/(2*coef[0]);
		x2=(-coef[1])/(2*coef[0]);
	}
	else if(delta<0) {
		x1=(-coef[1])/2*coef[0];
		x1im=Math.sqrt(-delta)/2*coef[0];
		x2=(-coef[1])/2*coef[0];
		x2im=-Math.sqrt(-delta)/2*coef[0];
	}
	else if(delta>0){
		x1 = ((-coef[1])+Math.sqrt(delta))/(2*coef[0]);
		x2 = ((-coef[1])-Math.sqrt(delta))/(2*coef[0]);
	}
	var radacini=[x1,x2,x1im,x2im];
	return radacini;
}

function showAnswer(radacini){
	if(radacini[2]||radacini[3]!=0){
		document.getElementById("x1").innerHTML = "x1 =" + radacini[0] + "+" + radacini[2] + "i";
		document.getElementById("x2").innerHTML = "x2 =" + radacini[1] + radacini[3] + "i";
	}
	else{
		document.getElementById("x1").innerHTML = "x1 =" + radacini[0];
		document.getElementById("x2").innerHTML = "x2 =" + radacini[1];
	}
	}

function solve(){
			// x1=x2=x1im=x2im=0;
			var coef = read();
			var delta = solveDelta(coef);
			var radacini=solveRoots(coef,delta);
			showAnswer(radacini);
			document.getElementById("delta").innerHTML = "Delta=" + delta;
			document.getElementById("aa").innerHTML = "a= " + coef[0];
			document.getElementById("bb").innerHTML = "b= " + coef[1];
			document.getElementById("cc").innerHTML = "c= " + coef[2];

		}
<|endoftext|>


<commit_before>
module.exports = function(skill, info, bot, message) {
  bot.reply(message, 'http://giphy.com/gifs/QGzPdYCcBbbZm'};
};
<commit_msg>Update BobTrump.js<commit_after>
module.exports = function(skill, info, bot, message) {
  bot.reply(message, 'http://i.giphy.com/QGzPdYCcBbbZm.gif'};
};
<|endoftext|>


<commit_before>const fs = require('fs')
const path = require('path')
const resolveBin = require('resolve-bin')
const spawn = require('cross-spawn')
const {fromRoot} = require('../utils')
const {hasPkgProp} = require('../utils')

const args = process.argv.slice(2)
const here = p => path.join(__dirname, p)

const useBuiltinConfig =
  !args.includes('--config') &&
  !fs.existsSync(fromRoot('.eslintrc')) &&
  !hasPkgProp('eslint')
const config = useBuiltinConfig
  ? ['--config', here('../config/eslintrc.js')]
  : []

const useBuiltinIgnore =
  !args.includes('--ignore-path') && !fs.existsSync(fromRoot('.eslintignore'))
const ignore = useBuiltinIgnore
  ? ['--ignore-path', here('../config/eslintignore')]
  : []

const cache = args.includes('--no-cache') ? [] : ['--cache']

const result = spawn.sync(
  resolveBin.sync('eslint'),
  [...config, ...ignore, ...cache, '.'].concat(args),
  {stdio: 'inherit'},
)

process.exit(result.status)
<commit_msg>fix(eslint): look for correct config in package.json<commit_after>const fs = require('fs')
const path = require('path')
const resolveBin = require('resolve-bin')
const spawn = require('cross-spawn')
const {fromRoot} = require('../utils')
const {hasPkgProp} = require('../utils')

const args = process.argv.slice(2)
const here = p => path.join(__dirname, p)

const useBuiltinConfig =
  !args.includes('--config') &&
  !fs.existsSync(fromRoot('.eslintrc')) &&
  !hasPkgProp('eslintConfig')
const config = useBuiltinConfig
  ? ['--config', here('../config/eslintrc.js')]
  : []

const useBuiltinIgnore =
  !args.includes('--ignore-path') && !fs.existsSync(fromRoot('.eslintignore'))
const ignore = useBuiltinIgnore
  ? ['--ignore-path', here('../config/eslintignore')]
  : []

const cache = args.includes('--no-cache') ? [] : ['--cache']

const result = spawn.sync(
  resolveBin.sync('eslint'),
  [...config, ...ignore, ...cache, '.'].concat(args),
  {stdio: 'inherit'},
)

process.exit(result.status)
<|endoftext|>


<commit_before>import Unit from 'Units/Unit';
import GameState from 'Game/GameState';
import GameMap from 'Game/GameMap';
import EntityManager from 'Entities/EntityManager';
import SelectionHandler from 'InputHandlers/SelectionHandler';
import CameraHandler from 'InputHandlers/CameraHandler';

export default function start() {
  var Phaser = window.Phaser;

  var game = new Phaser.Game(800, 600, Phaser.AUTO, '', {
    preload,
    create,
    update,
    render
  });

  var entityManager;
  var state;
  var map;
  var selectionHandler;
  var cameraHandler;
  var debugKey;

  function preload() {
    game.load.tilemap('map', 'assets/map2.json', null, Phaser.Tilemap.TILED_JSON);
    game.load.image('character', 'assets/images/character.png');
    game.load.image('tileset', 'assets/images/tile_sheet.png');
  }

  function create() {
    game.physics.startSystem(Phaser.Physics.ARCADE);
    game.canvas.oncontextmenu = (e) => e.preventDefault();

    state = new GameState(game);
    map = new GameMap({
      game,
      mapName: 'map',
      dimensions: { width: 160, height: 120 },
      tileDimensions: { width: 10, height: 10 },
      walkableTiles: [3,5,6,8],
      collisionTiles: [1]
    });

    // render the map
    map.render({
      tileset: 'main',
      tilesetImageKey: 'tileset',
      layer: 'main'
    });

    debugKey = game.input.keyboard.addKey(Phaser.Keyboard.P);
    debugKey.onDown.add(() => { debugger; });
    entityManager = new EntityManager({game});

    selectionHandler = new SelectionHandler({game, entityManager, map});
    selectionHandler.handle();

    // add camera
    {
      let { x, y } = map.tileCoordsToWorldCoords({x: 34, y: 30});
      let cameraProperties = {x, y, game, spriteKey: 'character', speed: 100};

      let cursors = game.input.keyboard.createCursorKeys();
      cameraHandler = new CameraHandler({game, entityManager, map, cursors, cameraProperties, edgePixels: 50});
      cameraHandler.handle();
    }

    // add random entities
    for(let xi = 30; xi <= 42; xi++)
    {
      for(let yi = 25; yi <= 30; yi++)
      {
        let { x, y } = map.tileCoordsToWorldCoords({x: xi, y: yi});
        entityManager.addUnit({x, y, game, spriteKey: 'character', speed: 100});
      }
    }

    console.log('From main!');

    /*
    {
      let { x, y } = map.tileCoordsToWorldCoords({x: 43, y: 27});
      let entityId = entityManager.addUnit({x, y, game, spriteKey: 'character', speed: 100});
      let entity = entityManager._entities[entityId];
      entity.moveTo(map.tileCoordsToWorldCoords({x:60, y:27}));
    }
    */

    /*
    {
      let { x, y } = map.tileCoordsToWorldCoords({x: 42, y: 30});
      entityManager.addUnit({x, y, game, spriteKey: 'character', speed: 100});
    }*/
  }

  function update() {
    entityManager.update(map);
  }

  function render() {
    game.debug.inputInfo(32, 32);

    // game.debug.geom(selectionHandler.selectionRect, '#0fffff');
    // game.debug.geom(cameraHandler.deadHorizontalRect, '#00ff00');
    // game.debug.geom(cameraHandler.deadVerticalRect, '#0000ff');
    entityManager.render();
  }
}
<commit_msg>Made the initial set of units a bit smaller.<commit_after>import Unit from 'Units/Unit';
import GameState from 'Game/GameState';
import GameMap from 'Game/GameMap';
import EntityManager from 'Entities/EntityManager';
import SelectionHandler from 'InputHandlers/SelectionHandler';
import CameraHandler from 'InputHandlers/CameraHandler';

export default function start() {
  var Phaser = window.Phaser;

  var game = new Phaser.Game(800, 600, Phaser.AUTO, '', {
    preload,
    create,
    update,
    render
  });

  var entityManager;
  var state;
  var map;
  var selectionHandler;
  var cameraHandler;
  var debugKey;

  function preload() {
    game.load.tilemap('map', 'assets/map2.json', null, Phaser.Tilemap.TILED_JSON);
    game.load.image('character', 'assets/images/character.png');
    game.load.image('tileset', 'assets/images/tile_sheet.png');
  }

  function create() {
    game.physics.startSystem(Phaser.Physics.ARCADE);
    game.canvas.oncontextmenu = (e) => e.preventDefault();

    state = new GameState(game);
    map = new GameMap({
      game,
      mapName: 'map',
      dimensions: { width: 160, height: 120 },
      tileDimensions: { width: 10, height: 10 },
      walkableTiles: [3,5,6,8],
      collisionTiles: [1]
    });

    // render the map
    map.render({
      tileset: 'main',
      tilesetImageKey: 'tileset',
      layer: 'main'
    });

    debugKey = game.input.keyboard.addKey(Phaser.Keyboard.P);
    debugKey.onDown.add(() => { debugger; });

    entityManager = new EntityManager({game});

    selectionHandler = new SelectionHandler({game, entityManager, map});
    selectionHandler.handle();

    // add camera
    {
      let { x, y } = map.tileCoordsToWorldCoords({x: 34, y: 30});
      let cameraProperties = {x, y, game, spriteKey: 'character', speed: 100};

      let cursors = game.input.keyboard.createCursorKeys();
      cameraHandler = new CameraHandler({game, entityManager, map, cursors, cameraProperties, edgePixels: 50});
      cameraHandler.handle();
    }

    // add random entities
    for(let xi = 30; xi <= 35; xi++)
    {
      for(let yi = 25; yi <= 25; yi++)
      {
        let { x, y } = map.tileCoordsToWorldCoords({x: xi, y: yi});
        entityManager.addUnit({x, y, game, spriteKey: 'character', speed: 100});
      }
    }
    /*
    {
      let { x, y } = map.tileCoordsToWorldCoords({x: 43, y: 27});
      let entityId = entityManager.addUnit({x, y, game, spriteKey: 'character', speed: 100});
      let entity = entityManager._entities[entityId];
      entity.moveTo(map.tileCoordsToWorldCoords({x:60, y:27}));
    }
    */

    /*
    {
      let { x, y } = map.tileCoordsToWorldCoords({x: 42, y: 30});
      entityManager.addUnit({x, y, game, spriteKey: 'character', speed: 100});
    }*/
  }

  function update() {
    entityManager.update(map);
  }

  function render() {
    game.debug.inputInfo(32, 32);

    // game.debug.geom(selectionHandler.selectionRect, '#0fffff');
    // game.debug.geom(cameraHandler.deadHorizontalRect, '#00ff00');
    // game.debug.geom(cameraHandler.deadVerticalRect, '#0000ff');
    entityManager.render();
  }
}
<|endoftext|>


<commit_before>(function() {

  function buildPaperModel() {
    var now = moment();
    return {
      text: '',
      id: now.toISOString(),
      dateUpdated: now,
      dateCreated: now
    };
  }

  var containerElement = document.querySelector('#chronopaper');

  function setState(_this, params) {
    _this.setState(Object.assign({}, _this.state, params));
    return _this;
  }

  var ContentEditable = React.createClass({
    getInitialState: function() {
      return {};
    },
    shouldComponentUpdate: function(nextProps, nextState) {
      //return this.props.value !== nextProps.value;
      return true;
    },

    handleTextChange: function(e) {
      //console.log(Object.assign({}, e));
      var text = '';
      if (!!e.target) {
        if (!!e.target.value) {
          text = e.target.value;
        } else if (!!e.target.innerText) {
          text = e.target.innerText;
        }
      }

      if (text !== this.lastValue) {
        this.lastValue = text;
        // Notify for paper submit
        if (this.props.onChange) {
          this.props.onChange(text);
        }
      }
    },

    render: function() {
      return (

{this.props.value}

          <textarea
            value={this.props.value}
            onChange={this.handleTextChange}></textarea>

      );
    }
  });

  var PaperForm = React.createClass({

    getInitialState: function() {
      return {
        view: 'editor'
      };
    },

    componentDidMount: function() {
      containerElement.querySelector('.expanding-area textarea').focus();
    },

    handleViewChange: function(e) {
      setState(this, {
        view: e.target.checked === true ? 'markdown' : 'editor'
      });
    },

    handlePaperTextChange: function(text) {
      //console.log(Object.assign({}, text));
      // update the paper
      var paper = Object.assign({}, this.props.paper, {
        text: text,
        dateUpdated: moment()
      });

      // Notify for paper submit
      if (this.props.onPaperSubmit) {
        // TODO create a hash ID for the paper
        this.props.onPaperSubmit(paper);
      }
    },

    handleNewPaper: function(e) {
      e.preventDefault();
      if (typeof this.props.onCreateNewPaper === 'function') {
        this.props.onCreateNewPaper();
      }
    },

    rawMarkup: function() {
      var rawMarkup = marked(this.props.paper.text, {sanitize: true});
      return { __html: rawMarkup };
    },

    render: function() {
      var editorView = null;
      if (this.state.view === 'editor') {
        editorView = (

              <ContentEditable onChange={this.handlePaperTextChange} value={this.props.paper.text}/>

            <button type="submit">Create New</button>

        );
      } else if (this.state.view === 'markdown') {
        editorView =
;
      }
      return (

          <form className="paper-form" onSubmit={this.handleNewPaper}>
            View Markdown<input id="chk-markdown" type="checkbox" value="markdown" onChange={this.handleViewChange} />
            { editorView }
          </form>

      );
    }
  });

  var Paper = React.createClass({
    onClick: function(e) {
      if (this.props.onClick) {
        this.props.onClick(e);
      }
    },

    shouldComponentUpdate: function(nextProps, nextState) {
      return this.props.paper.dateUpdated.toISOString() !== nextProps.paper.dateUpdated.toISOString();
    },

    render: function() {
      return (

Untitled paper - {this.props.paper.id}

          {this.props.paper.dateUpdated.toISOString()}

      );
    }
  });

  var PaperList = React.createClass({
    handlePaperOnClick: function(props, paper, idx) {
      if (typeof props.onSelectedPaper === 'function') {
        props.onSelectedPaper(paper, idx);
      }
    },

    render: function() {
      var _this = this;
      var paperNodes = this.props.papers.map(function(paper, idx) {
        return (

<Paper paper={paper} onClick={_this.handlePaperOnClick.bind(_this, _this.props, paper, idx)} />

        );
      }).reverse();
      return (

{paperNodes}

      );
    }
  });

  var PaperBox = React.createClass({
    getInitialState: function() {
      // TODO make the asynchronous code to fetch papers from the API
      return {
        papers: [buildPaperModel()],
        selectedPaperIdx: 0
      };
    },

    componentDidMount: function() {},

    handleOnSelectedPaper: function(paper, idx, previousPaper) {
      console.log('onSelectedPaper', paper, idx, previousPaper);
      setState(this, {
        selectedPaperIdx: idx
      });
    },

    handleOnPaperSubmit: function(paper) {
      // Make sure to edit the proper paper
      // For now we do not reorder the papers in any way
      var papers = this.state.papers;
      papers[this.state.selectedPaperIdx] = Object.assign({}, paper);
      setState(this, {papers: papers});
        // TODO send to the server and update the data[]
    },

    handleOnCreateNewPaper: function() {
      setState(this, {
        papers: this.state.papers.concat([buildPaperModel()]),
        selectedPaperIdx: this.state.papers.length
      });
    },

    render: function() {
      //console.log(Object.assign({}, this.state));
      return (

          <PaperList
            papers={this.state.papers}
            onSelectedPaper={this.handleOnSelectedPaper}/>
          <PaperForm
            paper={this.state.papers[this.state.selectedPaperIdx]}
            onPaperSubmit={this.handleOnPaperSubmit}
            onCreateNewPaper={this.handleOnCreateNewPaper} />

      );
    }
  });

  ReactDOM.render(
    <PaperBox />,
    containerElement
  );
}).call(this);<commit_msg>Using debounced onChange to avoid overhead of continuous updates.<commit_after>(function() {

  // https://john-dugan.com/javascript-debounce/
  function debounce(func, wait, immediate) {
    var timeout;
    return function() {
      var context = this,
      args = arguments;
      var later = function() {
        timeout = null;
        if (!immediate) {
          func.apply(context, args);
        }
      };
      var callNow = immediate && !timeout;
      clearTimeout(timeout);
      timeout = setTimeout(later, wait || 200);
      if (callNow) {
        func.apply(context, args);
      }
    };
  }

  function buildPaperModel() {
    var now = moment();
    return {
      text: '',
      id: now.toISOString(),
      dateUpdated: now,
      dateCreated: now
    };
  }

  var containerElement = document.querySelector('#chronopaper');

  function setState(_this, params) {
    _this.setState(Object.assign({}, _this.state, params));
    return _this;
  }

  var ContentEditable = React.createClass({
    getInitialState: function() {
      return {
        value: this.props.value
      };
    },

    shouldComponentUpdate: function(nextProps, nextState) {
      //return this.props.value !== nextProps.value;
      return true;
    },

    componentDidMount: function() {
      // create the debounced onChange method
      this.onChangeDebounced = debounce(function() {
        console.log('actual onChange');
        // Notify for paper submit
        if (this.props.onChange) {
          this.props.onChange(this.state.value);
        }
      }.bind(this));
    },

    componentWillReceiveProps: function(nextProps) {
      //console.log('componentWillReceiveProps', Object.assign({}, nextProps));
      setState(this, {
        value: nextProps.value
      });
    },

    handleTextChange: function(e) {
      //console.log(Object.assign({}, e));
      var text = e.target.value;

      this.setState({ value: text });
      this.onChangeDebounced();
    },

    render: function() {
      console.log('render');
      return (

{this.state.value}

          <textarea
            value={this.state.value}
            onChange={this.handleTextChange}></textarea>

      );
    }
  });

  var PaperForm = React.createClass({

    getInitialState: function() {
      return {
        view: 'editor'
      };
    },

    componentDidMount: function() {
      containerElement.querySelector('.expanding-area textarea').focus();
    },

    handleViewChange: function(e) {
      setState(this, {
        view: e.target.checked === true ? 'markdown' : 'editor'
      });
    },

    handlePaperTextChange: function(text) {
      //console.log(Object.assign({}, text));
      // update the paper
      var paper = Object.assign({}, this.props.paper, {
        text: text,
        dateUpdated: moment()
      });

      // Notify for paper submit
      if (this.props.onPaperSubmit) {
        // TODO create a hash ID for the paper
        this.props.onPaperSubmit(paper);
      }
    },

    handleNewPaper: function(e) {
      e.preventDefault();
      if (typeof this.props.onCreateNewPaper === 'function') {
        this.props.onCreateNewPaper();
      }
    },

    rawMarkup: function() {
      var rawMarkup = marked(this.props.paper.text, {sanitize: true});
      return { __html: rawMarkup };
    },

    render: function() {
      var editorView = null;
      if (this.state.view === 'editor') {
        editorView = (

              <ContentEditable onChange={this.handlePaperTextChange} value={this.props.paper.text}/>

            <button type="submit">Create New</button>

        );
      } else if (this.state.view === 'markdown') {
        editorView =
;
      }
      return (

          <form className="paper-form" onSubmit={this.handleNewPaper}>
            View Markdown<input id="chk-markdown" type="checkbox" value="markdown" onChange={this.handleViewChange} />
            { editorView }
          </form>

      );
    }
  });

  var Paper = React.createClass({
    onClick: function(e) {
      if (this.props.onClick) {
        this.props.onClick(e);
      }
    },

    shouldComponentUpdate: function(nextProps, nextState) {
      return this.props.paper.dateUpdated.toISOString() !== nextProps.paper.dateUpdated.toISOString();
    },

    render: function() {
      return (

Untitled paper - {this.props.paper.id}

          {this.props.paper.dateUpdated.toISOString()}

      );
    }
  });

  var PaperList = React.createClass({
    handlePaperOnClick: function(props, paper, idx) {
      if (typeof props.onSelectedPaper === 'function') {
        props.onSelectedPaper(paper, idx);
      }
    },

    render: function() {
      var _this = this;
      var paperNodes = this.props.papers.map(function(paper, idx) {
        return (

<Paper paper={paper} onClick={_this.handlePaperOnClick.bind(_this, _this.props, paper, idx)} />

        );
      }).reverse();
      return (

{paperNodes}

      );
    }
  });

  var PaperBox = React.createClass({
    getInitialState: function() {
      // TODO make the asynchronous code to fetch papers from the API
      return {
        papers: [buildPaperModel()],
        selectedPaperIdx: 0
      };
    },

    componentDidMount: function() {},

    handleOnSelectedPaper: function(paper, idx, previousPaper) {
      console.log('onSelectedPaper', paper, idx, previousPaper);
      setState(this, {
        selectedPaperIdx: idx
      });
    },

    handleOnPaperSubmit: function(paper) {
      // Make sure to edit the proper paper
      // For now we do not reorder the papers in any way
      var papers = this.state.papers;
      papers[this.state.selectedPaperIdx] = Object.assign({}, paper);
      setState(this, {papers: papers});
        // TODO send to the server and update the data[]
    },

    handleOnCreateNewPaper: function() {
      setState(this, {
        papers: this.state.papers.concat([buildPaperModel()]),
        selectedPaperIdx: this.state.papers.length
      });
    },

    render: function() {
      //console.log(Object.assign({}, this.state));
      return (

          <PaperList
            papers={this.state.papers}
            onSelectedPaper={this.handleOnSelectedPaper}/>
          <PaperForm
            paper={this.state.papers[this.state.selectedPaperIdx]}
            onPaperSubmit={this.handleOnPaperSubmit}
            onCreateNewPaper={this.handleOnCreateNewPaper} />

      );
    }
  });

  ReactDOM.render(
    <PaperBox />,
    containerElement
  );
}).call(this);<|endoftext|>


<commit_before>var mainElement = document.querySelector('main');

function checkForUnveil() {
    var windowTop = window.scrollY;
    var windowBottom = windowTop + window.innerHeight;
    var images = document.querySelectorAll('main img');

    for (var i = 0; i < images.length; i++) {
        var image = images[i];

        var elementTop = image.getBoundingClientRect().top;
        var elementBottom = elementTop + image.offsetHeight;

        if (elementBottom >= windowTop - 200 && elementTop <= windowBottom + 200) {
            var event = document.createEvent('HTMLEvents');
            event.initEvent('unveil', true, false);
            image.dispatchEvent(event);
        }
    }
}

function unveil(event) {
    var image = event.target || event.toElement;

    image.onload = function(event) {
        var second = new Image();
        second.src = event.currentTarget.getAttribute('data-src-second');
    };

    image.setAttribute('src', image.getAttribute('data-src'));

    image.removeEventListener('unveil', unveil);
}

mainElement.addEventListener('unveil', unveil);
function valse(event) {
    var image = event.currentTarget;
    var source = event.type === 'mousedown' || event.type === 'touchstart' ? image.getAttribute('data-src-second') : image.getAttribute('data-src');

    image.setAttribute('src', source);
}

for (var i = 0; i < images.length; i++) {
    images[i].addEventListener('unveil', unveil);
    images[i].addEventListener('mousedown', valse);
    images[i].addEventListener('mouseleave', valse);
    images[i].addEventListener('mouseup', valse);
    images[i].addEventListener('touchstart', valse);
    images[i].addEventListener('touchleave', valse);
    images[i].addEventListener('touchend', valse);
}

window.onscroll = checkForUnveil;
window.onresize = checkForUnveil;

checkForUnveil();
<commit_msg>Binding images' events on the main element<commit_after>var mainElement = document.querySelector('main');

function checkForUnveil() {
    var windowTop = window.scrollY;
    var windowBottom = windowTop + window.innerHeight;
    var images = document.querySelectorAll('main img');

    for (var i = 0; i < images.length; i++) {
        var image = images[i];

        var elementTop = image.getBoundingClientRect().top;
        var elementBottom = elementTop + image.offsetHeight;

        if (elementBottom >= windowTop - 200 && elementTop <= windowBottom + 200) {
            var event = document.createEvent('HTMLEvents');
            event.initEvent('unveil', true, false);
            image.dispatchEvent(event);
        }
    }
}

function unveil(event) {
    var image = event.target || event.toElement;

    image.onload = function(event) {
        var second = new Image();
        second.src = event.currentTarget.getAttribute('data-src-second');
    };

    image.setAttribute('src', image.getAttribute('data-src'));

    image.removeEventListener('unveil', unveil);
}

mainElement.addEventListener('unveil', unveil);

function valse(event) {
    var image = event.target || event.toElement;
    var showSecond = event.type === 'mousedown' || event.type === 'touchstart';
    var source = showSecond ? image.getAttribute('data-src-second') : image.getAttribute('data-src');

    image.setAttribute('src', source);
}

mainElement.addEventListener('mousedown', valse);
mainElement.addEventListener('mouseleave', valse);
mainElement.addEventListener('mouseup', valse);

mainElement.addEventListener('touchstart', valse);
mainElement.addEventListener('touchend', valse);

window.onscroll = checkForUnveil;
window.onresize = checkForUnveil;

checkForUnveil();
<|endoftext|>


<commit_before>// Description:
//   Slams from Ders and others
//
// Dependencies:
//   None
//
// Configuration:
//   None
//
// Commands:
//   (Slam|Burn) - Get Slammed
//
// Author:
//   taylor, andromedado

var images = [
    "http://38.media.tumblr.com/tumblr_m825bbnJIA1qam74xo1_500.gif",
    "http://33.media.tumblr.com/tumblr_m7dpky3KDX1rof6ulo1_500.gif",
    "http://i.imgur.com/ct3PcLA.gif",
    "http://reactiongif.org/wp-content/uploads/GIF/2014/08/GIF-amazing-classic-funny-OMG-rap-rapper-shocked-stare-Supa-Hot-Fire-surprised-GIF.gif",
    "http://media.giphy.com/media/xvWLAWTMsaEtG/giphy.gif",
    "http://data.whicdn.com/images/47936497/large.gif",
    "http://i58.photobucket.com/albums/g246/sey115/Photobucket%20Desktop%20-%20Sage%20Youngs%20MacBook/Funny%20and%20Random/willsmithsurprised_zpsbf418514.gif",
    "https://31.media.tumblr.com/1f7b873fec16573d26011e481ed0e50e/tumblr_inline_n1hy48UTMW1qklnuf.gif",
    "http://24.media.tumblr.com/tumblr_ma4vh18eP61rz79v5o2_500.gif",
    "http://massivnews.com/wp-content/uploads/2013/01/Christian-Bale-0001.gif",
    "https://38.media.tumblr.com/be1396e7b6d816233cad6deea60cff39/tumblr_nrkl22d6HW1tq4of6o1_400.gif",
    "https://d.gr-assets.com/hostedimages/1380365332ra/717283.gif",
    "https://i.imgur.com/2YnBth.jpg",
    "http://img1.wikia.nocookie.net/__cb20140712001317/survivor-org/images/5/59/Daaaamn.gif",
    "http://stream1.gifsoup.com/view7/2905081/daaaamn-o.gif",
    "http://imgur.com/xbKAw3s.gif",
    "http://24.media.tumblr.com/eea48b8232cd44ed1be871056a487998/tumblr_mly5rsm5nL1qbipv3o1_500.gif",
    "http://o.aolcdn.com/hss/storage/midas/c7c1534382efd62189f83a3461fd815c/200512318/andy-dwyer-gif.gif",
    "http://i.dailymail.co.uk/i/pix/2012/11/20/lakers_gif.gif",
    "http://i937.photobucket.com/albums/ad219/one_man_show_2010/lool.gif",
    "http://37.media.tumblr.com/91b05eeeceff90169f57a9c67d56de19/tumblr_mt8wwkvfXg1sin6fio1_500.gif",
    "http://i.imgur.com/PMdpq.gif",
    "http://i.imgur.com/M1yKgjm.gif",
    "http://wwwcache.wralsportsfan.com/asset/colleges/2015/01/23/14381597/horrified_crowd_reaction-288x209.gif",
    "https://media.giphy.com/media/QgixZj4y3TwnS/giphy.gif"
];

for (var i = 0; i < 130; i++) {
    images.push("http://media1.giphy.com/media/IfaFEvfGz8CXK/giphy.gif");
}

module.exports = function(robot) {
    return robot.hear(/dibsy (slam|burn)/i, function(msg) {
        return msg.send(msg.random(images) + "?_=" + (Math.ceil(Math.random() * 1000)));
    });
};

<commit_msg>regexes are (not )?fun<commit_after>// Description:
//   Slams from Ders and others
//
// Dependencies:
//   None
//
// Configuration:
//   None
//
// Commands:
//   Dibsy slam -- get slammed
//
// Author:
//   taylor, andromedado

var images = [
    "http://38.media.tumblr.com/tumblr_m825bbnJIA1qam74xo1_500.gif",
    "http://33.media.tumblr.com/tumblr_m7dpky3KDX1rof6ulo1_500.gif",
    "http://i.imgur.com/ct3PcLA.gif",
    "http://reactiongif.org/wp-content/uploads/GIF/2014/08/GIF-amazing-classic-funny-OMG-rap-rapper-shocked-stare-Supa-Hot-Fire-surprised-GIF.gif",
    "http://media.giphy.com/media/xvWLAWTMsaEtG/giphy.gif",
    "http://data.whicdn.com/images/47936497/large.gif",
    "http://i58.photobucket.com/albums/g246/sey115/Photobucket%20Desktop%20-%20Sage%20Youngs%20MacBook/Funny%20and%20Random/willsmithsurprised_zpsbf418514.gif",
    "https://31.media.tumblr.com/1f7b873fec16573d26011e481ed0e50e/tumblr_inline_n1hy48UTMW1qklnuf.gif",
    "http://24.media.tumblr.com/tumblr_ma4vh18eP61rz79v5o2_500.gif",
    "http://massivnews.com/wp-content/uploads/2013/01/Christian-Bale-0001.gif",
    "https://38.media.tumblr.com/be1396e7b6d816233cad6deea60cff39/tumblr_nrkl22d6HW1tq4of6o1_400.gif",
    "https://d.gr-assets.com/hostedimages/1380365332ra/717283.gif",
    "https://i.imgur.com/2YnBth.jpg",
    "http://img1.wikia.nocookie.net/__cb20140712001317/survivor-org/images/5/59/Daaaamn.gif",
    "http://stream1.gifsoup.com/view7/2905081/daaaamn-o.gif",
    "http://imgur.com/xbKAw3s.gif",
    "http://24.media.tumblr.com/eea48b8232cd44ed1be871056a487998/tumblr_mly5rsm5nL1qbipv3o1_500.gif",
    "http://o.aolcdn.com/hss/storage/midas/c7c1534382efd62189f83a3461fd815c/200512318/andy-dwyer-gif.gif",
    "http://i.dailymail.co.uk/i/pix/2012/11/20/lakers_gif.gif",
    "http://i937.photobucket.com/albums/ad219/one_man_show_2010/lool.gif",
    "http://37.media.tumblr.com/91b05eeeceff90169f57a9c67d56de19/tumblr_mt8wwkvfXg1sin6fio1_500.gif",
    "http://i.imgur.com/PMdpq.gif",
    "http://i.imgur.com/M1yKgjm.gif",
    "http://wwwcache.wralsportsfan.com/asset/colleges/2015/01/23/14381597/horrified_crowd_reaction-288x209.gif",
    "https://media.giphy.com/media/QgixZj4y3TwnS/giphy.gif"
];

for (var i = 0; i < 130; i++) {
    images.push("http://media1.giphy.com/media/IfaFEvfGz8CXK/giphy.gif");
}

module.exports = function(robot) {
    return robot.hear(/dibsy.*sa?lami?/i, function(msg) {
        return msg.send(msg.random(images) + "?_=" + (Math.ceil(Math.random() * 1000)));
    });
};

<|endoftext|>