<commit_before>import PropTypes from 'prop-types';
import React, { Component } from 'react';
import throttle from 'lodash.throttle';
import classNames from 'classnames';

import { isVideoChild, mediaProperties } from '../utils';

const propTypes = {
  actions: PropTypes.object,
  player: PropTypes.object,
  children: PropTypes.any,
  startTime: PropTypes.number,
  loop: PropTypes.bool,
  muted: PropTypes.bool,
  autoPlay: PropTypes.bool,
  playsInline: PropTypes.bool,
  src: PropTypes.string,
  poster: PropTypes.string,
  className: PropTypes.string,
  preload: PropTypes.oneOf(['auto', 'metadata', 'none']),

  onLoadStart: PropTypes.func,
  onWaiting: PropTypes.func,
  onCanPlay: PropTypes.func,
  onCanPlayThrough: PropTypes.func,
  onPlaying: PropTypes.func,
  onEnded: PropTypes.func,
  onSeeking: PropTypes.func,
  onSeeked: PropTypes.func,
  onPlay: PropTypes.func,
  onPause: PropTypes.func,
  onProgress: PropTypes.func,
  onDurationChange: PropTypes.func,
  onError: PropTypes.func,
  onSuspend: PropTypes.func,
  onAbort: PropTypes.func,
  onEmptied: PropTypes.func,
  onStalled: PropTypes.func,
  onLoadedMetadata: PropTypes.func,
  onLoadedData: PropTypes.func,
  onTimeUpdate: PropTypes.func,
  onRateChange: PropTypes.func,
  onVolumeChange: PropTypes.func,
  onResize: PropTypes.func,
};

const defaultProps = {
  preload: 'auto',
};

export default class Video extends Component {
  constructor(props) {
    super(props);

    this.video = null; // the html5 video
    this.play = this.play.bind(this);
    this.pause = this.pause.bind(this);
    this.seek = this.seek.bind(this);
    this.forward = this.forward.bind(this);
    this.replay = this.replay.bind(this);
    this.toggleFullscreen = this.toggleFullscreen.bind(this);
    this.getProperties = this.getProperties.bind(this);
    this.renderChildren = this.renderChildren.bind(this);
    this.handleLoadStart = this.handleLoadStart.bind(this);
    this.handleCanPlay = this.handleCanPlay.bind(this);
    this.handleCanPlayThrough = this.handleCanPlayThrough.bind(this);
    this.handlePlay = this.handlePlay.bind(this);
    this.handlePlaying = this.handlePlaying.bind(this);
    this.handlePause = this.handlePause.bind(this);
    this.handleEnded = this.handleEnded.bind(this);
    this.handleWaiting = this.handleWaiting.bind(this);
    this.handleSeeking = this.handleSeeking.bind(this);
    this.handleSeeked = this.handleSeeked.bind(this);
    this.handleFullscreenChange = this.handleFullscreenChange.bind(this);
    this.handleError = this.handleError.bind(this);
    this.handleSuspend = this.handleSuspend.bind(this);
    this.handleAbort = this.handleAbort.bind(this);
    this.handleEmptied = this.handleEmptied.bind(this);
    this.handleStalled = this.handleStalled.bind(this);
    this.handleLoadedMetaData = this.handleLoadedMetaData.bind(this);
    this.handleLoadedData = this.handleLoadedData.bind(this);
    this.handleTimeUpdate = this.handleTimeUpdate.bind(this);
    this.handleRateChange = this.handleRateChange.bind(this);
    this.handleVolumeChange = this.handleVolumeChange.bind(this);
    this.handleDurationChange = this.handleDurationChange.bind(this);
    this.handleProgress = throttle(this.handleProgress.bind(this), 250);
    this.handleKeypress = this.handleKeypress.bind(this);
  }

  componentDidMount() {
    this.forceUpdate(); // make sure the children can get the video property
  }

  // get all video properties
  getProperties() {
    if (!this.video) {
      return null;
    }

    return mediaProperties.reduce((properties, key) => {
      properties[key] = this.video[key];
      return properties;
    }, {});
  }

  // get playback rate
  get playbackRate() {
    return this.video.playbackRate;
  }

  // set playback rate
  // speed of video
  set playbackRate(rate) {
    this.video.playbackRate = rate;
  }

  get muted() {
    return this.video.muted;
  }

  set muted(val) {
    this.video.muted = val;
  }

  get volume() {
    return this.video.volume;
  }

  set volume(val) {
    if (val > 1) {
      val = 1;
    }
    if (val < 0) {
      val = 0;
    }
    this.video.volume = val;
  }

  // video width
  get videoWidth() {
    return this.video.videoWidth;
  }

  // video height
  get videoHeight() {
    return this.video.videoHeight;
  }

  // play the video
  play() {
    this.video.play();
  }

  // pause the video
  pause() {
    this.video.pause();
  }

  // Change the video source and re-load the video:
  load() {
    this.video.load();
  }

  // Add a new text track to the video
  addTextTrack(...args) {
    this.video.addTextTrack(...args);
  }

  // Check if your browser can play different types of video:
  canPlayType(...args) {
    this.video.canPlayType(...args);
  }

  // toggle play
  togglePlay() {
    if (this.video.paused) {
      this.play();
    } else {
      this.pause();
    }
  }

  // seek video by time
  seek(time) {
    try {
      this.video.currentTime = time;
    } catch (e) {
      // console.log(e, 'Video is not ready.')
    }
  }

  // jump forward x seconds
  forward(seconds) {
    this.seek(this.video.currentTime + seconds);
  }

  // jump back x seconds
  replay(seconds) {
    this.forward(-seconds);
  }

  // enter or exist full screen
  toggleFullscreen() {
    const { player, actions } = this.props;
    actions.toggleFullscreen(player);
  }

  // Fired when the user agent
  // begins looking for media data
  handleLoadStart(...args) {
    const { actions, onLoadStart } = this.props;
    actions.handleLoadStart(this.getProperties());
    if (onLoadStart) {
      onLoadStart(...args);
    }
  }

  // A handler for events that
  // signal that waiting has ended
  handleCanPlay(...args) {
    const { actions, onCanPlay } = this.props;

    actions.handleCanPlay(this.getProperties());

    if (onCanPlay) {
      onCanPlay(...args);
    }
  }

  // A handler for events that
  // signal that waiting has ended
  handleCanPlayThrough(...args) {
    const { actions, onCanPlayThrough } = this.props;
    actions.handleCanPlayThrough(this.getProperties());

    if (onCanPlayThrough) {
      onCanPlayThrough(...args);
    }
  }

  // A handler for events that
  // signal that waiting has ended
  handlePlaying(...args) {
    const { actions, onPlaying } = this.props;
    actions.handlePlaying(this.getProperties());

    if (onPlaying) {
      onPlaying(...args);
    }
  }

  // Fired whenever the media has been started
  handlePlay(...args) {
    const { actions, onPlay } = this.props;
    actions.handlePlay(this.getProperties());

    if (onPlay) {
      onPlay(...args);
    }
  }

  // Fired whenever the media has been paused
  handlePause(...args) {
    const { actions, onPause } = this.props;
    actions.handlePause(this.getProperties());

    if (onPause) {
      onPause(...args);
    }
  }

  // Fired when the duration of
  // the media resource is first known or changed
  handleDurationChange(...args) {
    const { actions, onDurationChange } = this.props;
    actions.handleDurationChange(this.getProperties());

    if (onDurationChange) {
      onDurationChange(...args);
    }
  }

  // Fired while the user agent
  // is downloading media data
  handleProgress(...args) {
    const { actions, onProgress } = this.props;
    if (this.video) {
      actions.handleProgressChange(this.getProperties());
    }

    if (onProgress) {
      onProgress(...args);
    }
  }

  // Fired when the end of the media resource
  // is reached (currentTime == duration)
  handleEnded(...args) {
    const { loop, player, actions, onEnded } = this.props;
    if (loop) {
      this.seek(0);
      this.play();
    } else if (!player.paused) {
      this.pause();
    }
    actions.handleEnd(this.getProperties());

    if (onEnded) {
      onEnded(...args);
    }
  }

  // Fired whenever the media begins waiting
  handleWaiting(...args) {
    const { actions, onWaiting } = this.props;
    actions.handleWaiting(this.getProperties());

    if (onWaiting) {
      onWaiting(...args);
    }
  }

  // Fired whenever the player
  // is jumping to a new time
  handleSeeking(...args) {
    const { actions, onSeeking } = this.props;
    actions.handleSeeking(this.getProperties());

    if (onSeeking) {
      onSeeking(...args);
    }
  }

  // Fired when the player has
  // finished jumping to a new time
  handleSeeked(...args) {
    const { actions, onSeeked } = this.props;
    actions.handleSeeked(this.getProperties());

    if (onSeeked) {
      onSeeked(...args);
    }
  }

  // Handle Fullscreen Change
  handleFullscreenChange() {
  }

  // Fires when the browser is
  // intentionally not getting media data
  handleSuspend(...args) {
    const { actions, onSuspend } = this.props;
    actions.handleSuspend(this.getProperties());
    if (onSuspend) {
      onSuspend(...args);
    }
  }

  // Fires when the loading of an audio/video is aborted
  handleAbort(...args) {
    const { actions, onAbort } = this.props;
    actions.handleAbort(this.getProperties());
    if (onAbort) {
      onAbort(...args);
    }
  }

  // Fires when the current playlist is empty
  handleEmptied(...args) {
    const { actions, onEmptied } = this.props;
    actions.handleEmptied(this.getProperties());
    if (onEmptied) {
      onEmptied(...args);
    }
  }

  // Fires when the browser is trying to
  // get media data, but data is not available
  handleStalled(...args) {
    const { actions, onStalled } = this.props;
    actions.handleStalled(this.getProperties());

    if (onStalled) {
      onStalled(...args);
    }
  }

  // Fires when the browser has loaded
  // meta data for the audio/video
  handleLoadedMetaData(...args) {
    const { actions, onLoadedMetadata, startTime } = this.props;

    if (startTime && startTime > 0) {
      this.video.currentTime = startTime;
    }

    actions.handleLoadedMetaData(this.getProperties());

    if (onLoadedMetadata) {
      onLoadedMetadata(...args);
    }
  }

  // Fires when the browser has loaded
  // the current frame of the audio/video
  handleLoadedData(...args) {
    const { actions, onLoadedData } = this.props;
    actions.handleLoadedData(this.getProperties());

    if (onLoadedData) {
      onLoadedData(...args);
    }
  }

  // Fires when the current
  // playback position has changed
  handleTimeUpdate(...args) {
    const { actions, onTimeUpdate } = this.props;
    actions.handleTimeUpdate(this.getProperties());

    if (onTimeUpdate) {
      onTimeUpdate(...args);
    }
  }

  /**
   * Fires when the playing speed of the audio/video is changed
   */
  handleRateChange(...args) {
    const { actions, onRateChange } = this.props;
    actions.handleRateChange(this.getProperties());

    if (onRateChange) {
      onRateChange(...args);
    }
  }

  // Fires when the volume has been changed
  handleVolumeChange(...args) {
    const { actions, onVolumeChange } = this.props;
    actions.handleVolumeChange(this.getProperties());

    if (onVolumeChange) {
      onVolumeChange(...args);
    }
  }

  // Fires when an error occurred
  // during the loading of an audio/video
  handleError(...args) {
    const { actions, onError } = this.props;
    actions.handleError(this.getProperties());
    if (onError) {
      onError(...args);
    }
  }

  handleResize(...args) {
    const { actions, onResize } = this.props;
    actions.handleResize(this.getProperties());
    if (onResize) {
      onResize(...args);
    }
  }

  handleKeypress() {

  }

  renderChildren() {
    const props = {
      ...this.props,
      video: this.video,
    };

    // to make sure the children can get video property
    if (!this.video) {
      return null;
    }

    // only keep <source />, <track />, <MyComponent isVideoChild /> elements
    return React.Children.toArray(this.props.children)
      .filter(isVideoChild)
      .map((c) => {
        let cprops;
        if (typeof c.type === 'string') {
          // add onError to <source />
          if (c.type === 'source') {
            cprops = { ...c.props };
            const preOnError = cprops.onError;
            cprops.onError = (...args) => {
              if (preOnError) {
                preOnError(...args);
              }
              this.handleError(...args);
            };
          }
        } else {
          cprops = props;
        }
        return React.cloneElement(
          c,
          cprops
        );
      });
  }

  render() {
    const {
      loop, poster, preload, src, autoPlay,
      playsInline, muted
    } = this.props;

    return (
      <video
        className={classNames(
          'video-react-video',
          this.props.className
        )}
        ref={(c) => { this.video = c; }}
        muted={muted}
        preload={preload}
        loop={loop}
        playsInline={playsInline}
        autoPlay={autoPlay}
        poster={poster}
        src={src}
        onLoadStart={this.handleLoadStart}
        onWaiting={this.handleWaiting}
        onCanPlay={this.handleCanPlay}
        onCanPlayThrough={this.handleCanPlayThrough}
        onPlaying={this.handlePlaying}
        onEnded={this.handleEnded}
        onSeeking={this.handleSeeking}
        onSeeked={this.handleSeeked}
        onPlay={this.handlePlay}
        onPause={this.handlePause}
        onProgress={this.handleProgress}
        onDurationChange={this.handleDurationChange}
        onError={this.handleError}
        onSuspend={this.handleSuspend}
        onAbort={this.handleAbort}
        onEmptied={this.handleEmptied}
        onStalled={this.handleStalled}
        onLoadedMetadata={this.handleLoadedMetaData}
        onLoadedData={this.handleLoadedData}
        onTimeUpdate={this.handleTimeUpdate}
        onRateChange={this.handleRateChange}
        onVolumeChange={this.handleVolumeChange}
      >
        {this.renderChildren()}
      </video>
    );
  }
}

Video.propTypes = propTypes;
Video.defaultProps = defaultProps;
<commit_msg>Add crossOrigin prop to Video<commit_after>import PropTypes from 'prop-types';
import React, { Component } from 'react';
import throttle from 'lodash.throttle';
import classNames from 'classnames';

import { isVideoChild, mediaProperties } from '../utils';

const propTypes = {
  actions: PropTypes.object,
  player: PropTypes.object,
  children: PropTypes.any,
  startTime: PropTypes.number,
  loop: PropTypes.bool,
  muted: PropTypes.bool,
  autoPlay: PropTypes.bool,
  playsInline: PropTypes.bool,
  src: PropTypes.string,
  poster: PropTypes.string,
  className: PropTypes.string,
  preload: PropTypes.oneOf(['auto', 'metadata', 'none']),
  crossOrigin: PropTypes.string,

  onLoadStart: PropTypes.func,
  onWaiting: PropTypes.func,
  onCanPlay: PropTypes.func,
  onCanPlayThrough: PropTypes.func,
  onPlaying: PropTypes.func,
  onEnded: PropTypes.func,
  onSeeking: PropTypes.func,
  onSeeked: PropTypes.func,
  onPlay: PropTypes.func,
  onPause: PropTypes.func,
  onProgress: PropTypes.func,
  onDurationChange: PropTypes.func,
  onError: PropTypes.func,
  onSuspend: PropTypes.func,
  onAbort: PropTypes.func,
  onEmptied: PropTypes.func,
  onStalled: PropTypes.func,
  onLoadedMetadata: PropTypes.func,
  onLoadedData: PropTypes.func,
  onTimeUpdate: PropTypes.func,
  onRateChange: PropTypes.func,
  onVolumeChange: PropTypes.func,
  onResize: PropTypes.func,
};

const defaultProps = {
  preload: 'auto',
};

export default class Video extends Component {
  constructor(props) {
    super(props);

    this.video = null; // the html5 video
    this.play = this.play.bind(this);
    this.pause = this.pause.bind(this);
    this.seek = this.seek.bind(this);
    this.forward = this.forward.bind(this);
    this.replay = this.replay.bind(this);
    this.toggleFullscreen = this.toggleFullscreen.bind(this);
    this.getProperties = this.getProperties.bind(this);
    this.renderChildren = this.renderChildren.bind(this);
    this.handleLoadStart = this.handleLoadStart.bind(this);
    this.handleCanPlay = this.handleCanPlay.bind(this);
    this.handleCanPlayThrough = this.handleCanPlayThrough.bind(this);
    this.handlePlay = this.handlePlay.bind(this);
    this.handlePlaying = this.handlePlaying.bind(this);
    this.handlePause = this.handlePause.bind(this);
    this.handleEnded = this.handleEnded.bind(this);
    this.handleWaiting = this.handleWaiting.bind(this);
    this.handleSeeking = this.handleSeeking.bind(this);
    this.handleSeeked = this.handleSeeked.bind(this);
    this.handleFullscreenChange = this.handleFullscreenChange.bind(this);
    this.handleError = this.handleError.bind(this);
    this.handleSuspend = this.handleSuspend.bind(this);
    this.handleAbort = this.handleAbort.bind(this);
    this.handleEmptied = this.handleEmptied.bind(this);
    this.handleStalled = this.handleStalled.bind(this);
    this.handleLoadedMetaData = this.handleLoadedMetaData.bind(this);
    this.handleLoadedData = this.handleLoadedData.bind(this);
    this.handleTimeUpdate = this.handleTimeUpdate.bind(this);
    this.handleRateChange = this.handleRateChange.bind(this);
    this.handleVolumeChange = this.handleVolumeChange.bind(this);
    this.handleDurationChange = this.handleDurationChange.bind(this);
    this.handleProgress = throttle(this.handleProgress.bind(this), 250);
    this.handleKeypress = this.handleKeypress.bind(this);
  }

  componentDidMount() {
    this.forceUpdate(); // make sure the children can get the video property
  }

  // get all video properties
  getProperties() {
    if (!this.video) {
      return null;
    }

    return mediaProperties.reduce((properties, key) => {
      properties[key] = this.video[key];
      return properties;
    }, {});
  }

  // get playback rate
  get playbackRate() {
    return this.video.playbackRate;
  }

  // set playback rate
  // speed of video
  set playbackRate(rate) {
    this.video.playbackRate = rate;
  }

  get muted() {
    return this.video.muted;
  }

  set muted(val) {
    this.video.muted = val;
  }

  get volume() {
    return this.video.volume;
  }

  set volume(val) {
    if (val > 1) {
      val = 1;
    }
    if (val < 0) {
      val = 0;
    }
    this.video.volume = val;
  }

  // video width
  get videoWidth() {
    return this.video.videoWidth;
  }

  // video height
  get videoHeight() {
    return this.video.videoHeight;
  }

  // play the video
  play() {
    this.video.play();
  }

  // pause the video
  pause() {
    this.video.pause();
  }

  // Change the video source and re-load the video:
  load() {
    this.video.load();
  }

  // Add a new text track to the video
  addTextTrack(...args) {
    this.video.addTextTrack(...args);
  }

  // Check if your browser can play different types of video:
  canPlayType(...args) {
    this.video.canPlayType(...args);
  }

  // toggle play
  togglePlay() {
    if (this.video.paused) {
      this.play();
    } else {
      this.pause();
    }
  }

  // seek video by time
  seek(time) {
    try {
      this.video.currentTime = time;
    } catch (e) {
      // console.log(e, 'Video is not ready.')
    }
  }

  // jump forward x seconds
  forward(seconds) {
    this.seek(this.video.currentTime + seconds);
  }

  // jump back x seconds
  replay(seconds) {
    this.forward(-seconds);
  }

  // enter or exist full screen
  toggleFullscreen() {
    const { player, actions } = this.props;
    actions.toggleFullscreen(player);
  }

  // Fired when the user agent
  // begins looking for media data
  handleLoadStart(...args) {
    const { actions, onLoadStart } = this.props;
    actions.handleLoadStart(this.getProperties());
    if (onLoadStart) {
      onLoadStart(...args);
    }
  }

  // A handler for events that
  // signal that waiting has ended
  handleCanPlay(...args) {
    const { actions, onCanPlay } = this.props;

    actions.handleCanPlay(this.getProperties());

    if (onCanPlay) {
      onCanPlay(...args);
    }
  }

  // A handler for events that
  // signal that waiting has ended
  handleCanPlayThrough(...args) {
    const { actions, onCanPlayThrough } = this.props;
    actions.handleCanPlayThrough(this.getProperties());

    if (onCanPlayThrough) {
      onCanPlayThrough(...args);
    }
  }

  // A handler for events that
  // signal that waiting has ended
  handlePlaying(...args) {
    const { actions, onPlaying } = this.props;
    actions.handlePlaying(this.getProperties());

    if (onPlaying) {
      onPlaying(...args);
    }
  }

  // Fired whenever the media has been started
  handlePlay(...args) {
    const { actions, onPlay } = this.props;
    actions.handlePlay(this.getProperties());

    if (onPlay) {
      onPlay(...args);
    }
  }

  // Fired whenever the media has been paused
  handlePause(...args) {
    const { actions, onPause } = this.props;
    actions.handlePause(this.getProperties());

    if (onPause) {
      onPause(...args);
    }
  }

  // Fired when the duration of
  // the media resource is first known or changed
  handleDurationChange(...args) {
    const { actions, onDurationChange } = this.props;
    actions.handleDurationChange(this.getProperties());

    if (onDurationChange) {
      onDurationChange(...args);
    }
  }

  // Fired while the user agent
  // is downloading media data
  handleProgress(...args) {
    const { actions, onProgress } = this.props;
    if (this.video) {
      actions.handleProgressChange(this.getProperties());
    }

    if (onProgress) {
      onProgress(...args);
    }
  }

  // Fired when the end of the media resource
  // is reached (currentTime == duration)
  handleEnded(...args) {
    const { loop, player, actions, onEnded } = this.props;
    if (loop) {
      this.seek(0);
      this.play();
    } else if (!player.paused) {
      this.pause();
    }
    actions.handleEnd(this.getProperties());

    if (onEnded) {
      onEnded(...args);
    }
  }

  // Fired whenever the media begins waiting
  handleWaiting(...args) {
    const { actions, onWaiting } = this.props;
    actions.handleWaiting(this.getProperties());

    if (onWaiting) {
      onWaiting(...args);
    }
  }

  // Fired whenever the player
  // is jumping to a new time
  handleSeeking(...args) {
    const { actions, onSeeking } = this.props;
    actions.handleSeeking(this.getProperties());

    if (onSeeking) {
      onSeeking(...args);
    }
  }

  // Fired when the player has
  // finished jumping to a new time
  handleSeeked(...args) {
    const { actions, onSeeked } = this.props;
    actions.handleSeeked(this.getProperties());

    if (onSeeked) {
      onSeeked(...args);
    }
  }

  // Handle Fullscreen Change
  handleFullscreenChange() {
  }

  // Fires when the browser is
  // intentionally not getting media data
  handleSuspend(...args) {
    const { actions, onSuspend } = this.props;
    actions.handleSuspend(this.getProperties());
    if (onSuspend) {
      onSuspend(...args);
    }
  }

  // Fires when the loading of an audio/video is aborted
  handleAbort(...args) {
    const { actions, onAbort } = this.props;
    actions.handleAbort(this.getProperties());
    if (onAbort) {
      onAbort(...args);
    }
  }

  // Fires when the current playlist is empty
  handleEmptied(...args) {
    const { actions, onEmptied } = this.props;
    actions.handleEmptied(this.getProperties());
    if (onEmptied) {
      onEmptied(...args);
    }
  }

  // Fires when the browser is trying to
  // get media data, but data is not available
  handleStalled(...args) {
    const { actions, onStalled } = this.props;
    actions.handleStalled(this.getProperties());

    if (onStalled) {
      onStalled(...args);
    }
  }

  // Fires when the browser has loaded
  // meta data for the audio/video
  handleLoadedMetaData(...args) {
    const { actions, onLoadedMetadata, startTime } = this.props;

    if (startTime && startTime > 0) {
      this.video.currentTime = startTime;
    }

    actions.handleLoadedMetaData(this.getProperties());

    if (onLoadedMetadata) {
      onLoadedMetadata(...args);
    }
  }

  // Fires when the browser has loaded
  // the current frame of the audio/video
  handleLoadedData(...args) {
    const { actions, onLoadedData } = this.props;
    actions.handleLoadedData(this.getProperties());

    if (onLoadedData) {
      onLoadedData(...args);
    }
  }

  // Fires when the current
  // playback position has changed
  handleTimeUpdate(...args) {
    const { actions, onTimeUpdate } = this.props;
    actions.handleTimeUpdate(this.getProperties());

    if (onTimeUpdate) {
      onTimeUpdate(...args);
    }
  }

  /**
   * Fires when the playing speed of the audio/video is changed
   */
  handleRateChange(...args) {
    const { actions, onRateChange } = this.props;
    actions.handleRateChange(this.getProperties());

    if (onRateChange) {
      onRateChange(...args);
    }
  }

  // Fires when the volume has been changed
  handleVolumeChange(...args) {
    const { actions, onVolumeChange } = this.props;
    actions.handleVolumeChange(this.getProperties());

    if (onVolumeChange) {
      onVolumeChange(...args);
    }
  }

  // Fires when an error occurred
  // during the loading of an audio/video
  handleError(...args) {
    const { actions, onError } = this.props;
    actions.handleError(this.getProperties());
    if (onError) {
      onError(...args);
    }
  }

  handleResize(...args) {
    const { actions, onResize } = this.props;
    actions.handleResize(this.getProperties());
    if (onResize) {
      onResize(...args);
    }
  }

  handleKeypress() {

  }

  renderChildren() {
    const props = {
      ...this.props,
      video: this.video,
    };

    // to make sure the children can get video property
    if (!this.video) {
      return null;
    }

    // only keep <source />, <track />, <MyComponent isVideoChild /> elements
    return React.Children.toArray(this.props.children)
      .filter(isVideoChild)
      .map((c) => {
        let cprops;
        if (typeof c.type === 'string') {
          // add onError to <source />
          if (c.type === 'source') {
            cprops = { ...c.props };
            const preOnError = cprops.onError;
            cprops.onError = (...args) => {
              if (preOnError) {
                preOnError(...args);
              }
              this.handleError(...args);
            };
          }
        } else {
          cprops = props;
        }
        return React.cloneElement(
          c,
          cprops
        );
      });
  }

  render() {
    const {
      loop, poster, preload, src, autoPlay,
      playsInline, muted, crossOrigin
    } = this.props;

    return (
      <video
        className={classNames(
          'video-react-video',
          this.props.className
        )}
        crossOrigin={crossOrigin}
        ref={(c) => { this.video = c; }}
        muted={muted}
        preload={preload}
        loop={loop}
        playsInline={playsInline}
        autoPlay={autoPlay}
        poster={poster}
        src={src}
        onLoadStart={this.handleLoadStart}
        onWaiting={this.handleWaiting}
        onCanPlay={this.handleCanPlay}
        onCanPlayThrough={this.handleCanPlayThrough}
        onPlaying={this.handlePlaying}
        onEnded={this.handleEnded}
        onSeeking={this.handleSeeking}
        onSeeked={this.handleSeeked}
        onPlay={this.handlePlay}
        onPause={this.handlePause}
        onProgress={this.handleProgress}
        onDurationChange={this.handleDurationChange}
        onError={this.handleError}
        onSuspend={this.handleSuspend}
        onAbort={this.handleAbort}
        onEmptied={this.handleEmptied}
        onStalled={this.handleStalled}
        onLoadedMetadata={this.handleLoadedMetaData}
        onLoadedData={this.handleLoadedData}
        onTimeUpdate={this.handleTimeUpdate}
        onRateChange={this.handleRateChange}
        onVolumeChange={this.handleVolumeChange}
      >
        {this.renderChildren()}
      </video>
    );
  }
}

Video.propTypes = propTypes;
Video.defaultProps = defaultProps;
<|endoftext|>


<commit_before>import React from 'react';

const questions = {
  what: {
    question: 'Was ist CosmoWiki.org?',
    answer:

          CosmoWiki.org ist ein gemeinnütziges, nicht-kommerzielles Projekt zur
          Verbreitung von Wissen über die Bereiche Astronomie und Raumfahrt.

          Mit der Wikipedia existiert ein gewaltiger Wissensschatz, der von
          Enthusiasten mit größter Sorgfalt für jedermann erstellt und gepflegt wird.
          Doch warum sollte dieser phantastische Speicher nicht über seine
          eigentlichen Grenzen hinaus genutzt werden?

          Wir recherchieren unzählige Informationen aus Wikipedia und anderen
          Quellen, sammeln, veknüpfen und bereiten sie hier in möglichst übersichtlicher Weise auf.
          CosmoWiki.org ist also ein zentraler Platz im Netz, an dem der Nutzer zwei der
          faszinierendsten Gebiete aus Wissenschaft und Technik auf neue Weise entdecken kann.

          CosmoWiki.org dient interessierten Laien ebenso wie begeisterten Amateuren
          und allen anderen Space-Fans. Jeder Nutzer kann hier frei das gewaltige
          Universum der Astronomie und Raumfahrt unter einem Dach entdecken,
          die Geschichte dieser zwei wohl bedeutendsten Bereiche menschlichen
          Schaffens erkunden und zielgerichtet Informationen über Personen, Orte oder Objekte finden.

          Selbst sind wir natürlich auch fasziniert von allem, was mit dem
          Weltall zu tun hat. So lautet unser Motto: Nutzer arbeiten für Nutzer!

          Ausblick:

          Dieses Projekt wird nie fertiggestellt sein, da sich auch Astronomie
          und Raumfahrt permanent weiterentwickeln. Unsere Datenbank wächst
          ständig um neue Inhalte an, bestehende Einträge werden um weitere
          interessante Fakten ergänzt. Zusätzlich wird auch die Seite selbst
          weiterentwickelt, neue Funktionen werden das Nutzererlebnis verbessern.
          Wir hoffen auch, CosmoWiki.org bald in anderen Sprachen anbieten zu können.

          Die Community ist das Zentrum dieser Seite. Wir setzen auf den
          Enthusiasmus von Amateuren genauso wie auf die Fachkenntnisse von
          Wissenschaftlern und Historikern um ein Werk zu schaffen, das auch
          kritischen Analysen standhält.

  },
  license: {
    question: 'Darf ich Inhalte von CosmoWiki.org verwenden? Unter welcher Lizenz steht CosmoWiki.org?',
    answer:

          Alle Inhalte von CosmoWiki.org und die von Wikipedia eingebundenen Inhalte
          stehen unter der
           Creative-Commons-Lizenz Attribution-ShareAlike 3.0 Unported (CC-by-sa-3.0), wenn nichts anderes ausgewiesen wird.

          Gemäß den Bestimmungen der von Wikipedia verwendeten Lizenz  CC-by-sa-3.0 weisen wir darauf hin,
          dass CosmoWiki.org Artikel oder Teile von Artikeln von Wikipedia verwendet und einbindet.
          Dadurch steht CosmoWiki.org ebenfalls unter der  Creative Commons Lizenz CC BY-SA 3.0.

          Sie dürfen:
Teilen — das Material in jedwedem Format oder Medium
          vervielfältigen und weiterverbreiten.
Bearbeiten — das Material
          remixen, verändern und darauf aufbauen und zwar für beliebige Zwecke, sogar kommerziell.

          Weitere Informationen zu der verwendeten Lizenz erhalten sie hier: http://creativecommons.org/licenses/by-sa/3.0/de/

  },
  contribute: {
    question: 'Wie kann ich helfen CosmoWiki.org zu verbessern?',
    answer:

          Sie sind Hobby-Astronom oder Professor der Astrophysik, Historiker oder
          interessierter Laie, Raumfahrt-Begeisterter oder Astronaut? Sie haben
          Fehler gefunden, möchten Daten ergänzen oder diese Seite auf andere Weise bereichern?
          Wenn Sie etwas zu CosmoWiki.org beitragen und das Projekt unterstützen möchten,
          dann kontaktieren Sie uns bitte hier.

          Software-Entwickler und Programmierer können auch
          auf Github an
          CosmoWiki.org mitarbeiten.

          Wir sind stets offen für Ihre Anregungen und Ideen, jede Hilfe ist willkommen.

  },
  thx: {
    question: 'Danke!',
    answer:

          An dieser Stelle möchten wir uns ganz herzlich
          bei Wikimedia, der
          Online-Enzyklopädie Wikipedia.org und
          seinen vielen freiwilligen Mitarbeitern für das größte Lexikon
          der Welt bedanken! Sie alle haben das Wissen der Menschheit in das
          21. Jahrhundert katapultiert und uns allen damit einen unschätzbaren Dienst erwiesen.

          Weiterhin bedanken wir uns von ganzem Herzen bei Wolfram Kriesing für
          die Programmierung des gesamten Unterbaus dieser Seite,
          unzählige andere Hilfestellungen rund um die Webprogrammierung und die
          generelle Unterstützung des Projektes.

  },
  contact: {
    question: 'Kontakt',
    answer:

        <form className="pure-u-3-4 pure-u-sm-2-3 pure-u-md-1-2 pure-u-lg-1-3">
          Ihr Name:
            <input type="text" id="contactName" name="name" />

          Ihre Mailadresse:
            <input type="email" id="contactMail" name="mail" />

          Betreff:
            <input type="text" id="contactSubject" name="subject" />

          Ihre Nachricht:
            <textarea id="contactMessage" name="message" cols="40" rows="10" />

          <button>Senden</button>
        </form>

  },
  imprint: {
    question: 'Impressum',
    answer:

  }
};

export default class AboutComponent extends React.Component {

  constructor() {
    super();
    this.state = {visibleSection: ''};
  }

  toggleCategory(category) {
    const newState = this.state.visibleSection === category ? '' : category;
    this.setState({visibleSection: newState});
  }

  render() {
    const buildToggleFunctionFor = category => this.toggleCategory.bind(this, category);
    const categories = Object.keys(questions);
    const isVisible = category => this.state.visibleSection === category;

    return (

Wir über uns

Ohne Idee keine Entwicklung

@wolfram pls make the links in #footerElse open the appropriate answers in the about-site

@wolfram pls make a auto-scroll to question, but not normal behaviour of internal links (covered by branding)

@wolfram pls make the contact form work, send mail to admin@cosmowiki.org

            {categories.map(category =>
              <Question category={category} toggleFunction={buildToggleFunctionFor(category)} isVisible={isVisible(category)} key={category} />)}

    )
  }

  componentWillMount() {
    const category = typeof window !== 'undefined' && window.location.hash.replace(/^#/, '');
    this.toggleCategory(category);
  }
}

const Question = ({toggleFunction, category, isVisible}) => {
  const {question, answer} = questions[category];
  const classNames = isVisible ? 'answer visible' : 'answer hidden';

  return (

      {' ' + question}

{answer}

  );
};
<commit_msg>about todo<commit_after>import React from 'react';

const questions = {
  what: {
    question: 'Was ist CosmoWiki.org?',
    answer:

          CosmoWiki.org ist ein gemeinnütziges, nicht-kommerzielles Projekt zur
          Verbreitung von Wissen über die Bereiche Astronomie und Raumfahrt.

          Mit der Wikipedia existiert ein gewaltiger Wissensschatz, der von
          Enthusiasten mit größter Sorgfalt für jedermann erstellt und gepflegt wird.
          Doch warum sollte dieser phantastische Speicher nicht über seine
          eigentlichen Grenzen hinaus genutzt werden?

          Wir recherchieren unzählige Informationen aus Wikipedia und anderen
          Quellen, sammeln, veknüpfen und bereiten sie hier in möglichst übersichtlicher Weise auf.
          CosmoWiki.org ist also ein zentraler Platz im Netz, an dem der Nutzer zwei der
          faszinierendsten Gebiete aus Wissenschaft und Technik auf neue Weise entdecken kann.

          CosmoWiki.org dient interessierten Laien ebenso wie begeisterten Amateuren
          und allen anderen Space-Fans. Jeder Nutzer kann hier frei das gewaltige
          Universum der Astronomie und Raumfahrt unter einem Dach entdecken,
          die Geschichte dieser zwei wohl bedeutendsten Bereiche menschlichen
          Schaffens erkunden und zielgerichtet Informationen über Personen, Orte oder Objekte finden.

          Selbst sind wir natürlich auch fasziniert von allem, was mit dem
          Weltall zu tun hat. So lautet unser Motto: Nutzer arbeiten für Nutzer!

          Ausblick:

          Dieses Projekt wird nie fertiggestellt sein, da sich auch Astronomie
          und Raumfahrt permanent weiterentwickeln. Unsere Datenbank wächst
          ständig um neue Inhalte an, bestehende Einträge werden um weitere
          interessante Fakten ergänzt. Zusätzlich wird auch die Seite selbst
          weiterentwickelt, neue Funktionen werden das Nutzererlebnis verbessern.
          Wir hoffen auch, CosmoWiki.org bald in anderen Sprachen anbieten zu können.

          Die Community ist das Zentrum dieser Seite. Wir setzen auf den
          Enthusiasmus von Amateuren genauso wie auf die Fachkenntnisse von
          Wissenschaftlern und Historikern um ein Werk zu schaffen, das auch
          kritischen Analysen standhält.

  },
  license: {
    question: 'Darf ich Inhalte von CosmoWiki.org verwenden? Unter welcher Lizenz steht CosmoWiki.org?',
    answer:

          Alle Inhalte von CosmoWiki.org und die von Wikipedia eingebundenen Inhalte
          stehen unter der
           Creative-Commons-Lizenz Attribution-ShareAlike 3.0 Unported (CC-by-sa-3.0), wenn nichts anderes ausgewiesen wird.

          Gemäß den Bestimmungen der von Wikipedia verwendeten Lizenz  CC-by-sa-3.0 weisen wir darauf hin,
          dass CosmoWiki.org Artikel oder Teile von Artikeln von Wikipedia verwendet und einbindet.
          Dadurch steht CosmoWiki.org ebenfalls unter der  Creative Commons Lizenz CC BY-SA 3.0.

          Sie dürfen:
Teilen — das Material in jedwedem Format oder Medium
          vervielfältigen und weiterverbreiten.
Bearbeiten — das Material
          remixen, verändern und darauf aufbauen und zwar für beliebige Zwecke, sogar kommerziell.

          Weitere Informationen zu der verwendeten Lizenz erhalten sie hier: http://creativecommons.org/licenses/by-sa/3.0/de/

  },
  contribute: {
    question: 'Wie kann ich helfen CosmoWiki.org zu verbessern?',
    answer:

          Sie sind Hobby-Astronom oder Professor der Astrophysik, Historiker oder
          interessierter Laie, Raumfahrt-Begeisterter oder Astronaut? Sie haben
          Fehler gefunden, möchten Daten ergänzen oder diese Seite auf andere Weise bereichern?
          Wenn Sie etwas zu CosmoWiki.org beitragen und das Projekt unterstützen möchten,
          dann kontaktieren Sie uns bitte hier.

          Software-Entwickler und Programmierer können auch
          auf Github an
          CosmoWiki.org mitarbeiten.

          Wir sind stets offen für Ihre Anregungen und Ideen, jede Hilfe ist willkommen.

  },
  thx: {
    question: 'Danke!',
    answer:

          An dieser Stelle möchten wir uns ganz herzlich
          bei Wikimedia, der
          Online-Enzyklopädie Wikipedia.org und
          seinen vielen freiwilligen Mitarbeitern für das größte Lexikon
          der Welt bedanken! Sie alle haben das Wissen der Menschheit in das
          21. Jahrhundert katapultiert und uns allen damit einen unschätzbaren Dienst erwiesen.

          Weiterhin bedanken wir uns von ganzem Herzen bei Wolfram Kriesing für
          die Programmierung des gesamten Unterbaus dieser Seite,
          unzählige andere Hilfestellungen rund um die Webprogrammierung und die
          generelle Unterstützung des Projektes.

  },
  contact: {
    question: 'Kontakt',
    answer:

        <form className="pure-u-3-4 pure-u-sm-2-3 pure-u-md-1-2 pure-u-lg-1-3">
          Ihr Name:
            <input type="text" id="contactName" name="name" />

          Ihre Mailadresse:
            <input type="email" id="contactMail" name="mail" />

          Betreff:
            <input type="text" id="contactSubject" name="subject" />

          Ihre Nachricht:
            <textarea id="contactMessage" name="message" cols="40" rows="10" />

          <button>Senden</button>
        </form>

  },
  imprint: {
    question: 'Impressum',
    answer:

  }
};

export default class AboutComponent extends React.Component {

  constructor() {
    super();
    this.state = {visibleSection: ''};
  }

  toggleCategory(category) {
    const newState = this.state.visibleSection === category ? '' : category;
    this.setState({visibleSection: newState});
  }

  render() {
    const buildToggleFunctionFor = category => this.toggleCategory.bind(this, category);
    const categories = Object.keys(questions);
    const isVisible = category => this.state.visibleSection === category;

    return (

Wir über uns

Ohne Idee keine Entwicklung

@wolfram pls make the links in #footerElse open the appropriate answers in the about-site

@wolfram pls when clicking on link in #footerElse do a auto-scroll to question and avoid covering by branding

@wolfram pls make the contact form work, send mail to admin@cosmowiki.org

            {categories.map(category =>
              <Question category={category} toggleFunction={buildToggleFunctionFor(category)} isVisible={isVisible(category)} key={category} />)}

    )
  }

  componentWillMount() {
    const category = typeof window !== 'undefined' && window.location.hash.replace(/^#/, '');
    this.toggleCategory(category);
  }
}

const Question = ({toggleFunction, category, isVisible}) => {
  const {question, answer} = questions[category];
  const classNames = isVisible ? 'answer visible' : 'answer hidden';

  return (

      {' ' + question}

{answer}

  );
};
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Clear from 'react-icons/lib/md/clear';
import Spacing from 'components/spacing';
import Text from 'components/text';
import { colors } from 'styles/color';

// Mapping of alert types to their corresponding background and text colors
const typeColorMap = {
  info: {
    color: colors.blue,
    background: colors.blueLight,
  },
  success: {
    color: colors.green,
    background: colors.greenLight,
  },
  warn: {
    color: colors.yellow,
    background: colors.yellowLight,
  },
  error: {
    color: colors.red,
    background: colors.redLight,
  },
};

// Mapping of alert types to their corresponding text sizes.
const textSizeMap = {
  alpha: 'iota',
  beta: 'kilo',
};

// Mapping of alert types to their container padding values.
const paddingMap = {
  alpha: '16px 22px',
  beta: '10px 15px',
};

/**
 * Educational status alerts.
 */
class Alert extends Component {
  static propTypes = {
    type: PropTypes.oneOf(['info', 'success', 'warn', 'error']),
    size: PropTypes.oneOf(['alpha', 'beta']),
    title: PropTypes.string.isRequired,
    message: PropTypes.oneOfType([
      PropTypes.string,
      PropTypes.element,
    ]).isRequired,
    dismissable: PropTypes.bool,
    style: PropTypes.object,
  };

  static defaultProps = {
    type: 'info',
    size: 'alpha',
    dismissable: false,
    style: {},
  };

  state = {
    isVisible: true,
  };

  handleDismiss = () => this.setState({ isVisible: false });

  render() {
    const { type, size, title, message, dismissable, style: overrides, ...proxyProps } = this.props;
    const { isVisible } = this.state;
    const { color, background } = typeColorMap[type];

    const style = {
      backgroundColor: background,
      padding: paddingMap[size],
      ...overrides,
    };

    const clearStyle = {
      cursor: 'pointer',
      float: 'right',
    };

    if (!isVisible) {
      return null;
    }

    return (
      <Spacing size="large" style={style} bottom {...proxyProps}>
        {
          dismissable && (
            <Text color="gray15" style={clearStyle} onClick={this.handleDismiss} inline>
              <Clear />
            </Text>
          )
        }

        <Text size={textSizeMap[size]} color={color} bold inline>
          {title}
        </Text>

        <Spacing size="small" left inline>
          <Text size={textSizeMap[size]} color={color} inline>
            {message}
          </Text>
        </Spacing>
      </Spacing>
    );
  }
}

export default Alert;
<commit_msg>Remove artbirary spacing under Alert<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Clear from 'react-icons/lib/md/clear';
import Spacing from 'components/spacing';
import Text from 'components/text';
import { colors } from 'styles/color';

// Mapping of alert types to their corresponding background and text colors
const typeColorMap = {
  info: {
    color: colors.blue,
    background: colors.blueLight,
  },
  success: {
    color: colors.green,
    background: colors.greenLight,
  },
  warn: {
    color: colors.yellow,
    background: colors.yellowLight,
  },
  error: {
    color: colors.red,
    background: colors.redLight,
  },
};

// Mapping of alert types to their corresponding text sizes.
const textSizeMap = {
  alpha: 'iota',
  beta: 'kilo',
};

// Mapping of alert types to their container padding values.
const paddingMap = {
  alpha: '16px 22px',
  beta: '10px 15px',
};

/**
 * Educational status alerts.
 */
class Alert extends Component {
  static propTypes = {
    type: PropTypes.oneOf(['info', 'success', 'warn', 'error']),
    size: PropTypes.oneOf(['alpha', 'beta']),
    title: PropTypes.string.isRequired,
    message: PropTypes.oneOfType([
      PropTypes.string,
      PropTypes.element,
    ]).isRequired,
    dismissable: PropTypes.bool,
    style: PropTypes.object,
  };

  static defaultProps = {
    type: 'info',
    size: 'alpha',
    dismissable: false,
    style: {},
  };

  state = {
    isVisible: true,
  };

  handleDismiss = () => this.setState({ isVisible: false });

  render() {
    const { type, size, title, message, dismissable, style: overrides, ...proxyProps } = this.props;
    const { isVisible } = this.state;
    const { color, background } = typeColorMap[type];

    const style = {
      backgroundColor: background,
      padding: paddingMap[size],
      ...overrides,
    };

    const clearStyle = {
      cursor: 'pointer',
      float: 'right',
    };

    if (!isVisible) {
      return null;
    }

    return (
      <div style={style} {...proxyProps}>
        {
          dismissable && (
            <Text color="gray15" style={clearStyle} onClick={this.handleDismiss} inline>
              <Clear />
            </Text>
          )
        }

        <Text size={textSizeMap[size]} color={color} bold inline>
          {title}
        </Text>

        <Spacing size="small" left inline>
          <Text size={textSizeMap[size]} color={color} inline>
            {message}
          </Text>
        </Spacing>
      </div>
    );
  }
}

export default Alert;
<|endoftext|>


<commit_before>import Radio from './radio/'
import DevTip from './dev-tip/'
import XInput from './x-input/'
import XNumber from './x-number/'
import Cell from './cell/'
import InlineDesc from './inline-desc/'
import Checklist from './checklist/'
import Switch from './switch/'
import XTextarea from './x-textarea/'
import Group from './group/'
import GroupTitle from './group-title/'
import Box from './box/'
import Tip from './tip/'
import Selector from './selector/'
import XButton from './x-button/'
import Flexbox from './flexbox/'
import FlexboxItem from './flexbox-item/'
import Tab from './tab/'
import TabItem from './tab-item/'
import Swiper from './swiper'
import SwiperItem from './swiper/Swiper-item'
import Sticky from './sticky/'
import Picker from './picker/'
import Datetime from './datetime/'
import Popup from './popup/'
import Range from './range/'
import Actionsheet from './actionsheet/'
import Clocker from './clocker/'
import Rater from './rater/'
import PopupPicker from './popup-picker/'
import Address from './address/'
import Toast from './toast/'
import Loading from './loading/'
import Alert from './alert/'
import Confirm from './confirm/'
import Progress from './progress/'
import XImg from './x-img/'
import Spinner from './spinner/'
import Calendar from './calendar/'
import Icon from './icon/'
import Circle from './circle/'
import Style from './Style'
import ColorPicker from './color-picker/'
import AddressChinaData from './address/list.json'
import Divider from './divider/'
import Blur from './blur/'
import Countup from './countup/'
import Scroller from './scroller/'
import Shake from './shake/'
import WechatEmotion from './wechat-emotion/'
import Search from './search'
import DateFormatter from './datetime/format'
import Masker from './masker'
import Countdown from './countdown'
import FriendlyTime from '../filters/friend-time'

const vux = {
  Radio,
  Group,
  DevTip,
  XInput,
  GroupTitle,
  XNumber,
  Checklist,
  Switch,
  Box,
  Tip,
  Selector,
  Cell,
  InlineDesc,
  XButton,
  XTextarea,
  Flexbox,
  FlexboxItem,
  Tab,
  TabItem,
  Swiper,
  SwiperItem,
  Sticky,
  Picker,
  Datetime,
  Popup,
  Range,
  Actionsheet,
  Clocker,
  Rater,
  PopupPicker,
  Address,
  Toast,
  Loading,
  Alert,
  Confirm,
  Progress,
  XImg,
  Spinner,
  Calendar,
  Icon,
  Circle,
  Style,
  ColorPicker,
  AddressChinaData,
  Divider,
  Blur,
  Countup,
  Scroller,
  Shake,
  WechatEmotion,
  Search,
  DateFormatter,
  Masker,
  Countdown,
  FriendlyTime
}

module.exports = vux

<commit_msg>Fix typo<commit_after>import Radio from './radio/'
import DevTip from './dev-tip/'
import XInput from './x-input/'
import XNumber from './x-number/'
import Cell from './cell/'
import InlineDesc from './inline-desc/'
import Checklist from './checklist/'
import Switch from './switch/'
import XTextarea from './x-textarea/'
import Group from './group/'
import GroupTitle from './group-title/'
import Box from './box/'
import Tip from './tip/'
import Selector from './selector/'
import XButton from './x-button/'
import Flexbox from './flexbox/'
import FlexboxItem from './flexbox-item/'
import Tab from './tab/'
import TabItem from './tab-item/'
import Swiper from './swiper'
import SwiperItem from './swiper/Swiper-item'
import Sticky from './sticky/'
import Picker from './picker/'
import Datetime from './datetime/'
import Popup from './popup/'
import Range from './range/'
import Actionsheet from './actionsheet/'
import Clocker from './clocker/'
import Rater from './rater/'
import PopupPicker from './popup-picker/'
import Address from './address/'
import Toast from './toast/'
import Loading from './loading/'
import Alert from './alert/'
import Confirm from './confirm/'
import Progress from './progress/'
import XImg from './x-img/'
import Spinner from './spinner/'
import Calendar from './calendar/'
import Icon from './icon/'
import Circle from './circle/'
import Style from './Style'
import ColorPicker from './color-picker/'
import AddressChinaData from './address/list.json'
import Divider from './divider/'
import Blur from './blur/'
import Countup from './countup/'
import Scroller from './scroller/'
import Shake from './shake/'
import WechatEmotion from './wechat-emotion/'
import Search from './search'
import DateFormatter from './datetime/format'
import Masker from './masker'
import Countdown from './countdown'
import FriendlyTime from '../filters/friendly-time'

const vux = {
  Radio,
  Group,
  DevTip,
  XInput,
  GroupTitle,
  XNumber,
  Checklist,
  Switch,
  Box,
  Tip,
  Selector,
  Cell,
  InlineDesc,
  XButton,
  XTextarea,
  Flexbox,
  FlexboxItem,
  Tab,
  TabItem,
  Swiper,
  SwiperItem,
  Sticky,
  Picker,
  Datetime,
  Popup,
  Range,
  Actionsheet,
  Clocker,
  Rater,
  PopupPicker,
  Address,
  Toast,
  Loading,
  Alert,
  Confirm,
  Progress,
  XImg,
  Spinner,
  Calendar,
  Icon,
  Circle,
  Style,
  ColorPicker,
  AddressChinaData,
  Divider,
  Blur,
  Countup,
  Scroller,
  Shake,
  WechatEmotion,
  Search,
  DateFormatter,
  Masker,
  Countdown,
  FriendlyTime
}

module.exports = vux

<|endoftext|>


<commit_before>
<commit_msg>Delete index.js<commit_after><|endoftext|>


<commit_before>import React, { Component } from "react";
import initialData from "../model";
import MD5 from "../utils";
import "../stylesheets/main.scss";

const ButtonTab = ({ active, onClick }) =>

Всплывающий
фрейм

Встроенный
фрейм

const ButtonSubmit = ({ value, show }) =>
show ?

  <button className="btn" type="submit">{value}</button>
 : false

const Input = ({ index, name, value, onChange }) => <input type="text" data-index={index} name={name} value={value} onChange={onChange} />;

const Card = ({ show, dataCard, onChange }) =>
show ?

VISA

    Номер карты:
    <Input name="pan" value={dataCard[0]} onChange={onChange} />

      Срок действия:
      <Input name="expire" value={dataCard[1]} onChange={onChange} />

      CVC/CVV:?
      <Input name="cvv" value={dataCard[2]} onChange={onChange} />

 : false

const ParentId = ({method}) =>
{ method == "set" ? parent_id: "iframe_parent", : false }

const Snippet = ({method, data, onClick}) =>

    copy{

‹script src="https://paymo.ru/paymentgate/iframe/checkout.js">‹/script›

‹script›

PaymoFrame.{method}({

      <ParentId method={method}/>

api_key: "{data[0].value}",

tx_id: "{data[1].value}",

description: "{data[2].value}",

amount: {data[3].value},

signature: "{data[6].value}",

success_redirect: "{data[4].value}",

fail_redirect: "{data[5].value}",

rebill: {},

extra: {},

version: "2.0.0"

})

      ‹/script›

      ‹div id="iframe_parent"›

      ‹/div›
    }

const Loader = ({show, pan, expire, cvv}) => show ?

Ожидание оплаты...

          curl -X POST -H 'Content-Type: application/json' -H 'X-Sign: {MD5(pan+expire+cvv)}' -d '{"pan":{pan},"expire":{expire},"cvv":{cvv}}' https://paymo.ru/paymentgate

 : false

export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: initialData,
      dataCard: ["411111111111","10/17","123"],
      activeTab: 1,
      method: "set",
      showCard: false,
      showRequest: false
    };
    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.handleSubmitRequest = this.handleSubmitRequest.bind(this);
    this.handleTabClick = this.handleTabClick.bind(this);
    this.handleCopyClick = this.handleCopyClick.bind(this);
  }

  handleChange(e) {
    if (e.target.hasAttribute("data-index")) {
      const data = this.state.data;
      data[e.target.getAttribute("data-index")].value = e.target.value;
      this.setState({ data });
    }
    const dataCard = this.state.dataCard;
    switch (e.target.name) {
        case "pan": dataCard[0] = e.target.value; break;
        case "expire": dataCard[1] = e.target.value; break;
        case "cvv": dataCard[2] = e.target.value; break;
    }
    this.setState({ dataCard });
    !e.target.value.length ? e.target.style.border = "1px solid red" : e.target.style.border = ""
  }

  handleSubmit(e) {
    e.preventDefault();
    const isTrue = this.state.data.some (
      el => !el.value.length
    )
    this.setState({showCard: !isTrue});
  }

  handleSubmitRequest(e) {
    e.preventDefault();
    const isTrue = this.state.dataCard.some (
      el => !el.length
    )
    this.setState({showCard: isTrue, showRequest: !isTrue});

  }

  handleTabClick(e) {
    const tab = +e.target.getAttribute("data-tab");
    this.setState({activeTab: tab})
    switch (tab) {
      case 1: this.setState({method: "set"}); break;
      case 2: this.setState({method: "open"}); break;
    }
  }

  handleCopyClick() {
    alert("handleCopyClick")
  }

  render() {
    const Fields = this.state.data.map (
        (el,index) =>
{el.label}<Input index={index} name={el.id} value={el.value} onChange={this.handleChange} />

    );
    return (
      <form name="frame" method="post" className="frames" onSubmit={this.state.showCard ? this.handleSubmitRequest : this.handleSubmit}>
        <ButtonTab onClick={this.handleTabClick} active={this.state.activeTab} />

            {Fields}

          <Snippet method={this.state.method} data={this.state.data} onClick={this.handleCopyClick} />

          <Card show={this.state.showCard} onChange={this.handleChange} dataCard={this.state.dataCard} />

        <Loader show={this.state.showRequest} pan={this.state.dataCard[0]} expire={this.state.dataCard[1]} cvv={this.state.dataCard[2]} />
        <ButtonSubmit value={this.state.showCard ? "Оплатить" : "Вызвать фрейм"} show={!this.state.showRequest} />
      </form>
    );
  }
}
<commit_msg>Updated App container section<commit_after>import React, { Component } from "react";
import initialData from "../model";
import MD5 from "../utils";
import "../stylesheets/main.scss";

const ButtonTab = ({ active, onClick }) =>

Всплывающий
фрейм

Встроенный
фрейм

const ButtonSubmit = ({ value, show }) =>
show ?

  <button className="btn" type="submit">{value}</button>
 : false

const Input = ({ index, name, value, onChange }) => <input type="text" data-index={index} name={name} value={value} onChange={onChange} />;

const Card = ({ show, dataCard, onChange }) =>
show ?

VISA

    Номер карты:
    <Input name="pan" value={dataCard[0]} onChange={onChange} />

      Срок действия:
      <Input name="expire" value={dataCard[1]} onChange={onChange} />

      CVC/CVV:?
      <Input name="cvv" value={dataCard[2]} onChange={onChange} />

 : false

const ParentId = ({method}) =>
{ method == "set" ? parent_id: "iframe_parent", : false }

const Snippet = ({method, data, onClick}) =>

    copy{

‹script src="https://paymo.ru/paymentgate/iframe/checkout.js">‹/script›

‹script›

PaymoFrame.{method}({

      <ParentId method={method}/>

api_key: "{data[0].value}",

tx_id: "{data[1].value}",

description: "{data[2].value}",

amount: {data[3].value},

signature: "{data[6].value}",

success_redirect: "{data[4].value}",

fail_redirect: "{data[5].value}",

rebill: {},

extra: {},

version: "2.0.0"

})

      ‹/script›

      ‹div id="iframe_parent"›

      ‹/div›
    }

const Loader = ({show, pan, expire, cvv}) => show ?

Ожидание оплаты...

          curl -X POST -H 'Content-Type: application/json' -H 'X-Sign: {MD5(pan+expire+cvv)}' -d '{"pan":{pan},"expire":{expire},"cvv":{cvv}}' https://paymo.ru/paymentgate

 : false

const Result = ({show, pan, expire, cvv}) => show ?

Оплата успешно проведена

Номер карты: {pan}

Срок действия: {expire}

CVV: {cvv}

 : false

export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: initialData,
      dataCard: ["411111111111","10/17","123"],
      activeTab: 1,
      method: "set",
      showCard: false,
      showRequest: false,
      showResult: false
    };
    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.handleSubmitRequest = this.handleSubmitRequest.bind(this);
    this.handleTabClick = this.handleTabClick.bind(this);
    this.handleCopyClick = this.handleCopyClick.bind(this);
  }

  handleChange(e) {
    if (e.target.hasAttribute("data-index")) {
      const data = this.state.data;
      data[e.target.getAttribute("data-index")].value = e.target.value;
      this.setState({ data });
    }
    const dataCard = this.state.dataCard;
    switch (e.target.name) {
        case "pan": dataCard[0] = e.target.value; break;
        case "expire": dataCard[1] = e.target.value; break;
        case "cvv": dataCard[2] = e.target.value; break;
    }
    this.setState({ dataCard });
    !e.target.value.length ? e.target.style.border = "1px solid red" : e.target.style.border = ""
  }

  handleSubmit(e) {
    e.preventDefault();
    const isTrue = this.state.data.some (
      el => !el.value.length
    )
    this.setState({showCard: !isTrue});
  }

  handleSubmitRequest(e) {
    e.preventDefault();
    const isTrue = this.state.dataCard.some (
      el => !el.length
    )
    this.setState({showCard: isTrue, showRequest: !isTrue});

    const requestObject = JSON.stringify({
      api_key: this.state.data[0].value,
      tx_id: this.state.data[1].value,
      description: this.state.data[2].value,
      amount: this.state.data[3].value,
      signature: this.state.data[6].value,
      success_redirect: this.state.data[4].value,
      fail_redirect: this.state.data[5].value,
      pan: this.state.dataCard[0],
      expire: this.state.dataCard[1],
      cvv: this.state.dataCard[2]
    });

    console.log(requestObject);

    setTimeout(() => {
        this.setState({showRequest: false, showResult: true});
      }, 3000);
  }

  handleTabClick(e) {
    const tab = +e.target.getAttribute("data-tab");
    this.setState({activeTab: tab})
    switch (tab) {
      case 1: this.setState({method: "set"}); break;
      case 2: this.setState({method: "open"}); break;
    }
  }

  handleCopyClick() {
    let codeText = document.getElementsByTagName('code')[0].textContent.replace(/‹/g,"<").replace(/›/g,">");
    alert(codeText);
  }

  render() {
    const Fields = this.state.data.map (
        (el,index) =>
{el.label}<Input index={index} name={el.id} value={el.value} onChange={this.handleChange} />

    );
    return (
      <form name="frame" method="post" className="frames" onSubmit={this.state.showCard ? this.handleSubmitRequest : this.handleSubmit}>
        <ButtonTab onClick={this.handleTabClick} active={this.state.activeTab} />

            {Fields}

          <Snippet method={this.state.method} data={this.state.data} onClick={this.handleCopyClick} />

          <Card show={this.state.showCard} onChange={this.handleChange} dataCard={this.state.dataCard} />

        <Loader show={this.state.showRequest} pan={this.state.dataCard[0]} expire={this.state.dataCard[1]} cvv={this.state.dataCard[2]} />
        <Result show={this.state.showResult} pan={this.state.dataCard[0]} expire={this.state.dataCard[1]} cvv={this.state.dataCard[2]} />
        <ButtonSubmit value={this.state.showCard ? "Оплатить" : "Вызвать фрейм"} show={this.state.showResult ? this.state.showRequest: !this.state.showRequest} />
      </form>
    );
  }
}
<|endoftext|>


<commit_before>/*
 This file is a part of libertysoil.org website
 Copyright (C) 2016  Loki Education (Social Enterprise)

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU Affero General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Affero General Public License for more details.

 You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
import React, { PropTypes } from 'react';
import { Link } from 'react-router';
import ga from 'react-google-analytics';

export default class LoginComponent extends React.Component {
  static displayName = 'LoginComponent';

  static propTypes = {
    onLoginUser: PropTypes.func.isRequired
  };

  submitHandler = (event) => {
    event.preventDefault();

    const form = event.target;

    this.props.onLoginUser(form.username.value, form.password.value).then(() => {
      ga('send', 'event', 'Login', 'Done');
    });
  };

  render() {
    return (
      <form action="" className="layout__grid layout__grid-responsive layout-align_end layout__space-double" method="post" onSubmit={this.submitHandler}>

          User name

            person

              <input
                autoCapitalize="none"
                autoCorrect="off"
                className="input input-big input-block"
                id="loginUsername"
                name="username"
                placeholder="Username"
                required="required"
                type="text"
              />

          Password

              <input className="input input-big input-block" id="loginPassword" name="password" placeholder="Password" required="required" type="password" />

            <Link className="link input_group__after input_group__after-outside_bottom" to="/resetpassword">Forgot your password?</Link>

          <button className="button button-big button-red">Log in</button>

      </form>
    );
  }
}
<commit_msg>login component refactor to use refs accessors to form inputs<commit_after>/*
 This file is a part of libertysoil.org website
 Copyright (C) 2016  Loki Education (Social Enterprise)

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU Affero General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Affero General Public License for more details.

 You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
import React, { PropTypes } from 'react';
import { Link } from 'react-router';
import ga from 'react-google-analytics';

export default class LoginComponent extends React.Component {
  static displayName = 'LoginComponent';

  static propTypes = {
    onLoginUser: PropTypes.func.isRequired
  };

  submitHandler = (event) => {
    event.preventDefault();

    this.props.onLoginUser(this.usernameInput.value, this.passwordInput.value).then(() => {
      ga('send', 'event', 'Login', 'Done');
    });
  };

  render() {
    return (
      <form action="" className="layout__grid layout__grid-responsive layout-align_end layout__space-double" method="post" onSubmit={this.submitHandler}>

          User name

            person

              <input
                autoCapitalize="none"
                autoCorrect="off"
                className="input input-big input-block"
                id="loginUsername"
                name="username"
                placeholder="Username"
                ref={(input) => {
                  return this.usernameInput = input;
                }}
                required="required"
                type="text"
              />

          Password

              <input
                className="input input-big input-block"
                id="loginPassword"
                name="password"
                placeholder="Password"
                ref={(input) => {
                  return this.passwordInput = input;
                }}
                required="required"
                type="password"
              />

            <Link className="link input_group__after input_group__after-outside_bottom" to="/resetpassword">Forgot your password?</Link>

          <button className="button button-big button-red">Log in</button>

      </form>
    );
  }
}
<|endoftext|>


<commit_before>jQuery.fn.extend({
	text: function( text ) {
		if ( typeof text !== "object" && text != null )
			return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );

		var ret = "";

		jQuery.each( text || this, function(){
			jQuery.each( this.childNodes, function(){
				if ( this.nodeType != 8 )
					ret += this.nodeType != 1 ?
						this.nodeValue :
						jQuery.fn.text( [ this ] );
			});
		});

		return ret;
	},

	wrapAll: function( html ) {
		if ( this[0] ) {
			// The elements to wrap the target around
			var wrap = jQuery( html, this[0].ownerDocument ).clone();

			if ( this[0].parentNode )
				wrap.insertBefore( this[0] );

			wrap.map(function(){
				var elem = this;

				while ( elem.firstChild )
					elem = elem.firstChild;

				return elem;
			}).append(this);
		}

		return this;
	},

	wrapInner: function( html ) {
		return this.each(function(){
			jQuery( this ).contents().wrapAll( html );
		});
	},

	wrap: function( html ) {
		return this.each(function(){
			jQuery( this ).wrapAll( html );
		});
	},

	append: function() {
		return this.domManip(arguments, true, function(elem){
			if (this.nodeType == 1)
				this.appendChild( elem );
		});
	},

	prepend: function() {
		return this.domManip(arguments, true, function(elem){
			if (this.nodeType == 1)
				this.insertBefore( elem, this.firstChild );
		});
	},

	before: function() {
		return this.domManip(arguments, false, function(elem){
			this.parentNode.insertBefore( elem, this );
		});
	},

	after: function() {
		return this.domManip(arguments, false, function(elem){
			this.parentNode.insertBefore( elem, this.nextSibling );
		});
	},

	clone: function( events ) {
		// Do the clone
		var ret = this.map(function(){
			if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
				// IE copies events bound via attachEvent when
				// using cloneNode. Calling detachEvent on the
				// clone will also remove the events from the orignal
				// In order to get around this, we use innerHTML.
				// Unfortunately, this means some modifications to
				// attributes in IE that are actually only stored
				// as properties will not be copied (such as the
				// the name attribute on an input).
				var html = this.outerHTML, ownerDocument = this.ownerDocument;
				if ( !html ) {
					var div = ownerDocument.createElement("div");
					div.appendChild( this.cloneNode(true) );
					html = div.innerHTML;
				}

				return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")], ownerDocument)[0];
			} else
				return this.cloneNode(true);
		});

		// Copy the events from the original to the clone
		if ( events === true ) {
			var orig = this.find("*").andSelf(), i = 0;

			ret.find("*").andSelf().each(function(){
				if ( this.nodeName !== orig[i].nodeName )
					return;

				var events = jQuery.data( orig[i], "events" );

				for ( var type in events ) {
					for ( var handler in events[ type ] ) {
						jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
					}
				}

				i++;
			});
		}

		// Return the cloned set
		return ret;
	},

	html: function( value ) {
		return value === undefined ?
			(this[0] ?
				this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") :
				null) :
			this.empty().append( value );
	},

	replaceWith: function( value ) {
		return this.after( value ).remove();
	},

	domManip: function( args, table, callback ) {
		var fragment, scripts, cacheable, cached, cacheresults, first;

		if ( this[0] ) {
			if ( args.length === 1 && typeof args[0] === "string" ) {
				cacheable = true;
				cacheresults = jQuery.fragments[ args[0] ];
				if ( cacheresults ) {
					if ( cacheresults !== 1 ) {
						fragment = cacheresults;
					}
					cached = true;
				}
			}

			if ( !fragment ) {
				fragment = (this[0].ownerDocument || this[0]).createDocumentFragment();
				scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment );
			}

			first = fragment.firstChild;

			if ( first ) {
				table = table && jQuery.nodeName( first, "tr" );

				for ( var i = 0, l = this.length; i < l; i++ ) {
					callback.call(
						table ?
							root(this[i], first) :
							this[i],
						cacheable || this.length > 1 || i > 0 ?
							fragment.cloneNode(true) :
							fragment
					);
				}
			}

			if ( scripts ) {
				jQuery.each( scripts, evalScript );
			}

			if ( cacheable ) {
				jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;
			}
		}

		return this;

		function root( elem, cur ) {
			return jQuery.nodeName(elem, "table") ?
				(elem.getElementsByTagName("tbody")[0] ||
				elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
				elem;
		}
	}
});

jQuery.fragments = {};

jQuery.each({
	appendTo: "append",
	prependTo: "prepend",
	insertBefore: "before",
	insertAfter: "after",
	replaceAll: "replaceWith"
}, function(name, original){
	jQuery.fn[ name ] = function( selector ) {
		var ret = [], insert = jQuery( selector );

		for ( var i = 0, l = insert.length; i < l; i++ ) {
			var elems = (i > 0 ? this.clone(true) : this).get();
			jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
			ret = ret.concat( elems );
		}

		return this.pushStack( ret, name, selector );
	};
});

jQuery.each({
	remove: function( selector ) {
		if ( !selector || jQuery.multiFilter( selector, [ this ] ).length ) {
			if ( this.nodeType === 1 ) {
				cleanData( jQuery("*", this).add(this) );
			}

			if ( this.parentNode ) {
				this.parentNode.removeChild( this );
			}
		}
	},

	empty: function() {
		// Remove element nodes and prevent memory leaks
		if ( this.nodeType === 1 ) {
			cleanData( jQuery("*", this) );
		}

		// Remove any remaining nodes
		while ( this.firstChild ) {
			this.removeChild( this.firstChild );
		}
	}
}, function(name, fn){
	jQuery.fn[ name ] = function(){
		return this.each( fn, arguments );
	};
});

jQuery.extend({
	clean: function( elems, context, fragment ) {
		context = context || document;

		// !context.createElement fails in IE with an error but returns typeof 'object'
		if ( typeof context.createElement === "undefined" )
			context = context.ownerDocument || context[0] && context[0].ownerDocument || document;

		// If a single string is passed in and it's a single tag
		// just do a createElement and skip the rest
		if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {
			var match = /^<(\w+)\s*\/?>$/.exec(elems[0]);
			if ( match )
				return [ context.createElement( match[1] ) ];
		}

		var ret = [], scripts = [], div = context.createElement("div");

		jQuery.each(elems, function(i, elem){
			if ( typeof elem === "number" )
				elem += '';

			if ( !elem )
				return;

			// Convert html string into DOM nodes
			if ( typeof elem === "string" ) {
				// Fix "XHTML"-style tags in all browsers
				elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
					return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
						all :
						front + "></" + tag + ">";
				});

				// Trim whitespace, otherwise indexOf won't work as expected
				var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase();

				var wrap =
					// option or optgroup
					!tags.indexOf("<opt") &&
					[ 1, "<select multiple='multiple'>", "</select>" ] ||

					!tags.indexOf("<leg") &&
					[ 1, "<fieldset>", "</fieldset>" ] ||

					tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
					[ 1, "
", "
" ] ||

					!tags.indexOf("<tr") &&
					[ 2, "

", "

" ] ||

				 	//
 matched above
					(!tags.indexOf("<td") || !tags.indexOf("<th")) &&
					[ 3, "

", "

" ] ||

					!tags.indexOf("<col") &&
					[ 2, "

<colgroup>", "</colgroup>
" ] ||

					// IE can't serialize <link> and


<commit_before>import { Vector3 } from './Vector3.js';
import { Sphere } from './Sphere.js';
import { Plane } from './Plane.js';

/**
 * @author mrdoob / http://mrdoob.com/
 * @author alteredq / http://alteredqualia.com/
 * @author bhouston / http://clara.io
 */

var _sphere;
var _vector;

function Frustum( p0, p1, p2, p3, p4, p5 ) {

	this.planes = [

		( p0 !== undefined ) ? p0 : new Plane(),
		( p1 !== undefined ) ? p1 : new Plane(),
		( p2 !== undefined ) ? p2 : new Plane(),
		( p3 !== undefined ) ? p3 : new Plane(),
		( p4 !== undefined ) ? p4 : new Plane(),
		( p5 !== undefined ) ? p5 : new Plane()

	];

}

Object.assign( Frustum.prototype, {

	set: function ( p0, p1, p2, p3, p4, p5 ) {

		var planes = this.planes;

		planes[ 0 ].copy( p0 );
		planes[ 1 ].copy( p1 );
		planes[ 2 ].copy( p2 );
		planes[ 3 ].copy( p3 );
		planes[ 4 ].copy( p4 );
		planes[ 5 ].copy( p5 );

		return this;

	},

	clone: function () {

		return new this.constructor().copy( this );

	},

	copy: function ( frustum ) {

		var planes = this.planes;

		for ( var i = 0; i < 6; i ++ ) {

			planes[ i ].copy( frustum.planes[ i ] );

		}

		return this;

	},

	setFromMatrix: function ( m ) {

		var planes = this.planes;
		var me = m.elements;
		var me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];
		var me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];
		var me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];
		var me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];

		planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();
		planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();
		planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
		planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
		planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();
		planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();

		return this;

	},

	intersectsObject: function ( object ) {

		if ( _sphere === undefined ) _sphere = new Sphere();

		var geometry = object.geometry;

		if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();

		_sphere.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld );

		return this.intersectsSphere( _sphere );

	},

	intersectsSprite: function ( sprite ) {

		_sphere.center.set( 0, 0, 0 );
		_sphere.radius = 0.7071067811865476;
		_sphere.applyMatrix4( sprite.matrixWorld );

		return this.intersectsSphere( _sphere );

	},

	intersectsSphere: function ( sphere ) {

		var planes = this.planes;
		var center = sphere.center;
		var negRadius = - sphere.radius;

		for ( var i = 0; i < 6; i ++ ) {

			var distance = planes[ i ].distanceToPoint( center );

			if ( distance < negRadius ) {

				return false;

			}

		}

		return true;

	},

	intersectsBox: function ( box ) {

		if ( _vector === undefined ) _vector = new Vector3();

		var planes = this.planes;

		for ( var i = 0; i < 6; i ++ ) {

			var plane = planes[ i ];

			// corner at max distance

			_vector.x = plane.normal.x > 0 ? box.max.x : box.min.x;
			_vector.y = plane.normal.y > 0 ? box.max.y : box.min.y;
			_vector.z = plane.normal.z > 0 ? box.max.z : box.min.z;

			if ( plane.distanceToPoint( _vector ) < 0 ) {

				return false;

			}

		}

		return true;

	},

	containsPoint: function ( point ) {

		var planes = this.planes;

		for ( var i = 0; i < 6; i ++ ) {

			if ( planes[ i ].distanceToPoint( point ) < 0 ) {

				return false;

			}

		}

		return true;

	}

} );

export { Frustum };
<commit_msg>Frustum: Add missing clsoure variable check.<commit_after>import { Vector3 } from './Vector3.js';
import { Sphere } from './Sphere.js';
import { Plane } from './Plane.js';

/**
 * @author mrdoob / http://mrdoob.com/
 * @author alteredq / http://alteredqualia.com/
 * @author bhouston / http://clara.io
 */

var _sphere;
var _vector;

function Frustum( p0, p1, p2, p3, p4, p5 ) {

	this.planes = [

		( p0 !== undefined ) ? p0 : new Plane(),
		( p1 !== undefined ) ? p1 : new Plane(),
		( p2 !== undefined ) ? p2 : new Plane(),
		( p3 !== undefined ) ? p3 : new Plane(),
		( p4 !== undefined ) ? p4 : new Plane(),
		( p5 !== undefined ) ? p5 : new Plane()

	];

}

Object.assign( Frustum.prototype, {

	set: function ( p0, p1, p2, p3, p4, p5 ) {

		var planes = this.planes;

		planes[ 0 ].copy( p0 );
		planes[ 1 ].copy( p1 );
		planes[ 2 ].copy( p2 );
		planes[ 3 ].copy( p3 );
		planes[ 4 ].copy( p4 );
		planes[ 5 ].copy( p5 );

		return this;

	},

	clone: function () {

		return new this.constructor().copy( this );

	},

	copy: function ( frustum ) {

		var planes = this.planes;

		for ( var i = 0; i < 6; i ++ ) {

			planes[ i ].copy( frustum.planes[ i ] );

		}

		return this;

	},

	setFromMatrix: function ( m ) {

		var planes = this.planes;
		var me = m.elements;
		var me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];
		var me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];
		var me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];
		var me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];

		planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();
		planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();
		planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
		planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
		planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();
		planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();

		return this;

	},

	intersectsObject: function ( object ) {

		if ( _sphere === undefined ) _sphere = new Sphere();

		var geometry = object.geometry;

		if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();

		_sphere.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld );

		return this.intersectsSphere( _sphere );

	},

	intersectsSprite: function ( sprite ) {

		if ( _sphere === undefined ) _sphere = new Sphere();

		_sphere.center.set( 0, 0, 0 );
		_sphere.radius = 0.7071067811865476;
		_sphere.applyMatrix4( sprite.matrixWorld );

		return this.intersectsSphere( _sphere );

	},

	intersectsSphere: function ( sphere ) {

		var planes = this.planes;
		var center = sphere.center;
		var negRadius = - sphere.radius;

		for ( var i = 0; i < 6; i ++ ) {

			var distance = planes[ i ].distanceToPoint( center );

			if ( distance < negRadius ) {

				return false;

			}

		}

		return true;

	},

	intersectsBox: function ( box ) {

		if ( _vector === undefined ) _vector = new Vector3();

		var planes = this.planes;

		for ( var i = 0; i < 6; i ++ ) {

			var plane = planes[ i ];

			// corner at max distance

			_vector.x = plane.normal.x > 0 ? box.max.x : box.min.x;
			_vector.y = plane.normal.y > 0 ? box.max.y : box.min.y;
			_vector.z = plane.normal.z > 0 ? box.max.z : box.min.z;

			if ( plane.distanceToPoint( _vector ) < 0 ) {

				return false;

			}

		}

		return true;

	},

	containsPoint: function ( point ) {

		var planes = this.planes;

		for ( var i = 0; i < 6; i ++ ) {

			if ( planes[ i ].distanceToPoint( point ) < 0 ) {

				return false;

			}

		}

		return true;

	}

} );

export { Frustum };
<|endoftext|>


<commit_before>/**
 * @author mrdoob / http://mrdoob.com/
 * @author philogb / http://blog.thejit.org/
 * @author egraether / http://egraether.com/
 * @author zz85 / http://www.lab4games.net/zz85/blog
 */

THREE.Vector2 = function ( x, y ) {

	this.x = x || 0;
	this.y = y || 0;

};

THREE.Vector2.prototype = {

	constructor: THREE.Vector2,

	set: function ( x, y ) {

		this.x = x;
		this.y = y;

		return this;

	},

	setX: function ( x ) {

		this.x = x;

		return this;

	},

	setY: function ( y ) {

		this.y = y;

		return this;

	},

	setComponent: function ( index, value ) {

		switch ( index ) {

			case 0: this.x = value; break;
			case 1: this.y = value; break;
			default: throw new Error( 'index is out of range: ' + index );

		}

	},

	getComponent: function ( index ) {

		switch ( index ) {

			case 0: return this.x;
			case 1: return this.y;
			default: throw new Error( 'index is out of range: ' + index );

		}

	},

	copy: function ( v ) {

		this.x = v.x;
		this.y = v.y;

		return this;

	},

	add: function ( v, w ) {

		if ( w !== undefined ) {

			console.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
			return this.addVectors( v, w );

		}

		this.x += v.x;
		this.y += v.y;

		return this;

	},

	addVectors: function ( a, b ) {

		this.x = a.x + b.x;
		this.y = a.y + b.y;

		return this;

	},

	addScalar: function ( s ) {

		this.x += s;
		this.y += s;

		return this;

	},

	sub: function ( v, w ) {

		if ( w !== undefined ) {

			console.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
			return this.subVectors( v, w );

		}

		this.x -= v.x;
		this.y -= v.y;

		return this;

	},

	subVectors: function ( a, b ) {

		this.x = a.x - b.x;
		this.y = a.y - b.y;

		return this;

	},

	multiply: function ( v ) {

		this.x *= v.x;
		this.y *= v.y;

		return this;

	},

	multiplyScalar: function ( s ) {

		this.x *= s;
		this.y *= s;

		return this;

	},

	divide: function ( v ) {

		this.x /= v.x;
		this.y /= v.y;

		return this;

	},

	divideScalar: function ( scalar ) {

		if ( scalar !== 0 ) {

			var invScalar = 1 / scalar;

			this.x *= invScalar;
			this.y *= invScalar;

		} else {

			this.x = 0;
			this.y = 0;

		}

		return this;

	},

	min: function ( v ) {

		if ( this.x > v.x ) {

			this.x = v.x;

		}

		if ( this.y > v.y ) {

			this.y = v.y;

		}

		return this;

	},

	max: function ( v ) {

		if ( this.x < v.x ) {

			this.x = v.x;

		}

		if ( this.y < v.y ) {

			this.y = v.y;

		}

		return this;

	},

	clamp: function ( min, max ) {

		// This function assumes min < max, if this assumption isn't true it will not operate correctly

		if ( this.x < min.x ) {

			this.x = min.x;

		} else if ( this.x > max.x ) {

			this.x = max.x;

		}

		if ( this.y < min.y ) {

			this.y = min.y;

		} else if ( this.y > max.y ) {

			this.y = max.y;

		}

		return this;
	},

	clampScalar: ( function () {

		var min, max;

		return function ( minVal, maxVal ) {

			if ( min === undefined ) {

				min = new THREE.Vector2();
				max = new THREE.Vector2();

			}

			min.set( minVal, minVal );
			max.set( maxVal, maxVal );

			return this.clamp( min, max );

		};

	} )(),

	floor: function () {

		this.x = Math.floor( this.x );
		this.y = Math.floor( this.y );

		return this;

	},

	ceil: function () {

		this.x = Math.ceil( this.x );
		this.y = Math.ceil( this.y );

		return this;

	},

	round: function () {

		this.x = Math.round( this.x );
		this.y = Math.round( this.y );

		return this;

	},

	roundToZero: function () {

		this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
		this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );

		return this;

	},

	negate: function () {

		this.x = - this.x;
		this.y = - this.y;

		return this;

	},

	dot: function ( v ) {

		return this.x * v.x + this.y * v.y;

	},

	lengthSq: function () {

		return this.x * this.x + this.y * this.y;

	},

	length: function () {

		return Math.sqrt( this.x * this.x + this.y * this.y );

	},

	normalize: function () {

		return this.divideScalar( this.length() );

	},

	distanceTo: function ( v ) {

		return Math.sqrt( this.distanceToSquared( v ) );

	},

	distanceToSquared: function ( v ) {

		var dx = this.x - v.x, dy = this.y - v.y;
		return dx * dx + dy * dy;

	},

	setLength: function ( l ) {

		var oldLength = this.length();

		if ( oldLength !== 0 && l !== oldLength ) {

			this.multiplyScalar( l / oldLength );
		}

		return this;

	},

	lerp: function ( v, alpha ) {

		this.x += ( v.x - this.x ) * alpha;
		this.y += ( v.y - this.y ) * alpha;

		return this;

	},

	equals: function ( v ) {

		return ( ( v.x === this.x ) && ( v.y === this.y ) );

	},

	fromArray: function ( array, offset ) {

		if ( offset === undefined ) offset = 0;

		this.x = array[ offset ];
		this.y = array[ offset + 1 ];

		return this;

	},

	toArray: function ( array, offset ) {

		if ( array ) {

			if ( offset === undefined ) offset = 0;

			array[ offset ] = this.x;
			array[ offset + 1 ] = this.y;

		} else {

			return [ this.x, this.y ];

		}

	},

	clone: function () {

		return new THREE.Vector2( this.x, this.y );

	}

};
<commit_msg>Vector2 toArray(): return array<commit_after>/**
 * @author mrdoob / http://mrdoob.com/
 * @author philogb / http://blog.thejit.org/
 * @author egraether / http://egraether.com/
 * @author zz85 / http://www.lab4games.net/zz85/blog
 */

THREE.Vector2 = function ( x, y ) {

	this.x = x || 0;
	this.y = y || 0;

};

THREE.Vector2.prototype = {

	constructor: THREE.Vector2,

	set: function ( x, y ) {

		this.x = x;
		this.y = y;

		return this;

	},

	setX: function ( x ) {

		this.x = x;

		return this;

	},

	setY: function ( y ) {

		this.y = y;

		return this;

	},

	setComponent: function ( index, value ) {

		switch ( index ) {

			case 0: this.x = value; break;
			case 1: this.y = value; break;
			default: throw new Error( 'index is out of range: ' + index );

		}

	},

	getComponent: function ( index ) {

		switch ( index ) {

			case 0: return this.x;
			case 1: return this.y;
			default: throw new Error( 'index is out of range: ' + index );

		}

	},

	copy: function ( v ) {

		this.x = v.x;
		this.y = v.y;

		return this;

	},

	add: function ( v, w ) {

		if ( w !== undefined ) {

			console.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
			return this.addVectors( v, w );

		}

		this.x += v.x;
		this.y += v.y;

		return this;

	},

	addVectors: function ( a, b ) {

		this.x = a.x + b.x;
		this.y = a.y + b.y;

		return this;

	},

	addScalar: function ( s ) {

		this.x += s;
		this.y += s;

		return this;

	},

	sub: function ( v, w ) {

		if ( w !== undefined ) {

			console.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
			return this.subVectors( v, w );

		}

		this.x -= v.x;
		this.y -= v.y;

		return this;

	},

	subVectors: function ( a, b ) {

		this.x = a.x - b.x;
		this.y = a.y - b.y;

		return this;

	},

	multiply: function ( v ) {

		this.x *= v.x;
		this.y *= v.y;

		return this;

	},

	multiplyScalar: function ( s ) {

		this.x *= s;
		this.y *= s;

		return this;

	},

	divide: function ( v ) {

		this.x /= v.x;
		this.y /= v.y;

		return this;

	},

	divideScalar: function ( scalar ) {

		if ( scalar !== 0 ) {

			var invScalar = 1 / scalar;

			this.x *= invScalar;
			this.y *= invScalar;

		} else {

			this.x = 0;
			this.y = 0;

		}

		return this;

	},

	min: function ( v ) {

		if ( this.x > v.x ) {

			this.x = v.x;

		}

		if ( this.y > v.y ) {

			this.y = v.y;

		}

		return this;

	},

	max: function ( v ) {

		if ( this.x < v.x ) {

			this.x = v.x;

		}

		if ( this.y < v.y ) {

			this.y = v.y;

		}

		return this;

	},

	clamp: function ( min, max ) {

		// This function assumes min < max, if this assumption isn't true it will not operate correctly

		if ( this.x < min.x ) {

			this.x = min.x;

		} else if ( this.x > max.x ) {

			this.x = max.x;

		}

		if ( this.y < min.y ) {

			this.y = min.y;

		} else if ( this.y > max.y ) {

			this.y = max.y;

		}

		return this;
	},

	clampScalar: ( function () {

		var min, max;

		return function ( minVal, maxVal ) {

			if ( min === undefined ) {

				min = new THREE.Vector2();
				max = new THREE.Vector2();

			}

			min.set( minVal, minVal );
			max.set( maxVal, maxVal );

			return this.clamp( min, max );

		};

	} )(),

	floor: function () {

		this.x = Math.floor( this.x );
		this.y = Math.floor( this.y );

		return this;

	},

	ceil: function () {

		this.x = Math.ceil( this.x );
		this.y = Math.ceil( this.y );

		return this;

	},

	round: function () {

		this.x = Math.round( this.x );
		this.y = Math.round( this.y );

		return this;

	},

	roundToZero: function () {

		this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
		this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );

		return this;

	},

	negate: function () {

		this.x = - this.x;
		this.y = - this.y;

		return this;

	},

	dot: function ( v ) {

		return this.x * v.x + this.y * v.y;

	},

	lengthSq: function () {

		return this.x * this.x + this.y * this.y;

	},

	length: function () {

		return Math.sqrt( this.x * this.x + this.y * this.y );

	},

	normalize: function () {

		return this.divideScalar( this.length() );

	},

	distanceTo: function ( v ) {

		return Math.sqrt( this.distanceToSquared( v ) );

	},

	distanceToSquared: function ( v ) {

		var dx = this.x - v.x, dy = this.y - v.y;
		return dx * dx + dy * dy;

	},

	setLength: function ( l ) {

		var oldLength = this.length();

		if ( oldLength !== 0 && l !== oldLength ) {

			this.multiplyScalar( l / oldLength );
		}

		return this;

	},

	lerp: function ( v, alpha ) {

		this.x += ( v.x - this.x ) * alpha;
		this.y += ( v.y - this.y ) * alpha;

		return this;

	},

	equals: function ( v ) {

		return ( ( v.x === this.x ) && ( v.y === this.y ) );

	},

	fromArray: function ( array, offset ) {

		if ( offset === undefined ) offset = 0;

		this.x = array[ offset ];
		this.y = array[ offset + 1 ];

		return this;

	},

	toArray: function ( array, offset ) {

		if ( array ) {

			if ( offset === undefined ) offset = 0;

			array[ offset ] = this.x;
			array[ offset + 1 ] = this.y;

			return array;

		} else {

			return [ this.x, this.y ];

		}

	},

	clone: function () {

		return new THREE.Vector2( this.x, this.y );

	}

};
<|endoftext|>


<commit_before>import childProcess from 'child_process'
import fs from 'fs'
import path from 'path'

const platformScriptNames = [
  'build',
  'deploy',
  'push',
  'run'
]

export function exec () {
  const { app, program, server, type } = this
  let command, scriptFile
  // execute a script
  const script = program.script
  if (typeof script !== 'undefined' && server) {
    let platform = program.platform
    let typedScript = script
    if (platformScriptNames.includes(script) && platform) {
      typedScript = `${platform}_${script}`
    }
    if (type) {
      typedScript = `${type.name}_${script}`
    }
    // find the file
    const scriptFileDir = path.join(server.dir, 'scripts', `${typedScript}.sh`)
    scriptFile = fs.readFileSync(scriptFileDir).toString('utf-8')
    command = `cd ${server.dir} && sh scripts/${typedScript}.sh`
  } else if (typeof program.method !== 'string') {
    console.log('You didn\'t specify a method to be called, please use the --method option for that')
    return
  // execute a command
  } else {
    command = program.lang === 'py'
    ? `python ${app.pythonDir} ${program.method.replace(/[ ]*,[ ]*|[ ]+/g, ' ')}`
    : this[program.method]()
  }
  // venv check
  if (app.venvDir) {
    command = `source ${app.venvDir}/bin/activate && ${command}`
  }
  // ttab check
  if (program.ttab === 'true') {
    command = `${app.ttabDir} \"${command}\"`
  }
  if (program.shell !== 'concurrently') {
    this.consoleInfo('Let\'s exec this command !')
    this.consoleLog(command)
    if (scriptFile) {
      this.consoleInfo('Which corresponds to : ')
      this.consoleLog(scriptFile)
    }
    childProcess.execSync(command, { stdio: [0, 1, 2] })
  } else if (script) {
    this.execAddConcurrently(script, command)
  }
}

export function execResetConcurrently (script) {
  this[`${script}ConcurrentlyCommands`] = []
}

export function execAddConcurrently (script, command) {
  this[`${script}ConcurrentlyCommands`].push(command)
}

export function execConcurrentlyOrDirectly(script) {
  const { program } = this
  if (program.shell !== 'concurrently') {
    if (program.user === 'me' && program.ttab === 'true') {
      command = `${command} --ttab true`
      this.consoleInfo(`Let\'s ${script}`)
      this.consoleLog(command)
      childProcess.execSync(command, { stdio: [0, 1, 2] })
    }
  }
  else {
    const concurrentlyCommandsString = this[`${script}ConcurrentlyCommands`]
      .map(concurrentlyCommand => `\"${concurrentlyCommand}\"`)
      .join(' ')
    const command = `${app.concurrentlyDir} --kill-others ${concurrentlyCommandsString}`
    this.consoleLog(command)
    childProcess.execSync(command, { stdio: [0, 1, 2] })
  }
}
<commit_msg>fix exec<commit_after>import childProcess from 'child_process'
import fs from 'fs'
import path from 'path'

const platformScriptNames = [
  'build',
  'deploy',
  'push',
  'run'
]

export function exec () {
  const { app, program, server, type } = this
  let command, scriptFile
  // execute a script
  const script = program.script
  if (typeof script !== 'undefined' && server) {
    let platform = program.platform
    let typedScript = script
    if (platformScriptNames.includes(script) && platform) {
      typedScript = `${platform}_${script}`
    }
    if (type) {
      typedScript = `${type.name}_${script}`
    }
    // find the file
    const scriptFileDir = path.join(server.dir, 'scripts', `${typedScript}.sh`)
    scriptFile = fs.readFileSync(scriptFileDir).toString('utf-8')
    command = `cd ${server.dir} && sh scripts/${typedScript}.sh`
  } else if (typeof program.method !== 'string') {
    console.log('You didn\'t specify a method to be called, please use the --method option for that')
    return
  // execute a command
  } else {
    command = program.lang === 'py'
    ? `python ${app.pythonDir} ${program.method.replace(/[ ]*,[ ]*|[ ]+/g, ' ')}`
    : this[program.method]()
  }
  // venv check
  if (app.venvDir) {
    command = `source ${app.venvDir}/bin/activate && ${command}`
  }
  // ttab check
  if (program.ttab === 'true') {
    command = `${app.ttabDir} \"${command}\"`
  }
  if (program.shell !== 'concurrently') {
    this.consoleInfo('Let\'s exec this command !')
    this.consoleLog(command)
    if (scriptFile) {
      this.consoleInfo('Which corresponds to : ')
      this.consoleLog(scriptFile)
    }
    childProcess.execSync(command, { stdio: [0, 1, 2] })
  } else if (script) {
    this.execAddConcurrently(script, command)
    childProcess.execSync(this[`${script}ConcurrentlyCommands`], { stdio: [0, 1, 2] })
  } else {
    childProcess.execSync(command, { stdio: [0, 1, 2] })
  }
}

export function execResetConcurrently (script) {
  this[`${script}ConcurrentlyCommands`] = []
}

export function execAddConcurrently (script, command) {
  if ( this[`${script}ConcurrentlyCommands`] === undefined ) {
    this[`${script}ConcurrentlyCommands`] = []
  }
  this[`${script}ConcurrentlyCommands`].push(command)
}

export function execConcurrentlyOrDirectly(script) {
  const { program } = this
  if (program.shell !== 'concurrently') {
    if (program.user === 'me' && program.ttab === 'true') {
      command = `${command} --ttab true`
      this.consoleInfo(`Let\'s ${script}`)
      this.consoleLog(command)
      childProcess.execSync(command, { stdio: [0, 1, 2] })
    }
  }
  else {
    const concurrentlyCommandsString = this[`${script}ConcurrentlyCommands`]
      .map(concurrentlyCommand => `\"${concurrentlyCommand}\"`)
      .join(' ')
    const command = `${app.concurrentlyDir} --kill-others ${concurrentlyCommandsString}`
    this.consoleLog(command)
    childProcess.execSync(command, { stdio: [0, 1, 2] })
  }
}
<|endoftext|>