<commit_before>import React, { PropTypes } from 'react';
import ReactDOM from 'react-dom';
import Remarkable from 'remarkable';
import { HotKeys } from 'react-hotkeys';
import { throttle } from 'lodash';
import isArray from 'lodash/isArray';
import { Checkbox, Form, Input, Select, Tabs } from 'antd';
import EditorToolbar from './EditorToolbar';
import Action from '../Button/Action';
import Body from '../Story/Body';
import './Editor.less';

const remarkable = new Remarkable();

const TabPane = Tabs.TabPane;

class Editor extends React.Component {
  static propTypes = {
    form: PropTypes.shape().isRequired,
    title: PropTypes.string,
    topics: PropTypes.arrayOf(PropTypes.string),
    body: PropTypes.string,
    reward: PropTypes.string,
    upvote: PropTypes.bool,
    loading: PropTypes.bool,
    onUpdate: PropTypes.func,
    onSubmit: PropTypes.func,
    onError: PropTypes.func,
    onImagePasted: PropTypes.func,
  };

  static defaultProps = {
    title: '',
    topics: [],
    body: '',
    reward: '50',
    upvote: true,
    recentTopics: [],
    popularTopics: [],
    loading: false,
    onUpdate: () => {},
    onSubmit: () => {},
    onError: () => {},
    onImagePasted: () => {},
  };

  static hotkeys = {
    h1: 'ctrl+shift+1',
    h2: 'ctrl+shift+2',
    h3: 'ctrl+shift+3',
    h4: 'ctrl+shift+4',
    h5: 'ctrl+shift+5',
    h6: 'ctrl+shift+6',
    bold: 'ctrl+b',
    italic: 'ctrl+i',
    quote: 'ctrl+q',
    link: 'ctrl+k',
    image: 'ctrl+m',
  };

  state = {
    contentHtml: '',
    noContent: false,
  };

  componentDidMount() {
    if (this.input) {
      this.input.addEventListener('input', throttle(e => this.renderMarkdown(e.target.value), 500));
      this.input.addEventListener('paste', this.handlePastedImage);
    }

    this.setValues(this.props);

    // eslint-disable-next-line react/no-find-dom-node
    const select = ReactDOM.findDOMNode(this.select);
    if (select) {
      const selectInput = select.querySelector('input,textarea,div[contentEditable]');
      if (selectInput) {
        selectInput.setAttribute('autocorrect', 'off');
        selectInput.setAttribute('autocapitalize', 'none');
      }
    }
  }

  componentWillReceiveProps(nextProps) {
    const { title, topics, body, reward, upvote } = this.props;
    if (
      title !== nextProps.title ||
      topics !== nextProps.topics ||
      body !== nextProps.body ||
      reward !== nextProps.reward ||
      upvote !== nextProps.upvote
    ) {
      this.setValues(nextProps);
    }
  }

  onUpdate = (e) => {
    // NOTE: antd doesn't update field value on Select before firing onChange
    // so we have to get value from event.
    this.props.onUpdate(this.getValues(e));
  };

  setInput = (input) => {
    if (input && input.refs && input.refs.input) {
      // eslint-disable-next-line react/no-find-dom-node
      this.input = ReactDOM.findDOMNode(input.refs.input);
    }
  };

  setValues = (post) => {
    this.props.form.setFieldsValue({
      title: post.title,
      topics: post.topics,
      reward: post.reward,
      upvote: post.upvote,
    });
    if (this.input) {
      this.input.value = post.body;
      this.renderMarkdown(this.input.value);
    }
  };

  getValues = (e) => {
    // NOTE: antd API is inconsistent and returns event or just value depending of input type.
    // this code extracts value from event based of event type
    // (array or just value for Select, proxy event for inputs and checkboxes)

    const values = {
      ...this.props.form.getFieldsValue(['title', 'topics', 'reward', 'upvote']),
      body: this.input.value,
    };

    if (isArray(e)) {
      values.topics = e;
    } else if (typeof e === 'string') {
      values.reward = e;
    } else if (e.target.type === 'textarea') {
      values.body = e.target.value;
    } else if (e.target.type === 'text') {
      values.title = e.target.value;
    } else if (e.target.type === 'checkbox') {
      values.upvote = e.target.checked;
    }<commit_msg>Fix pasting error in Editor<commit_after>import React, { PropTypes } from 'react';
import ReactDOM from 'react-dom';
import Remarkable from 'remarkable';
import { HotKeys } from 'react-hotkeys';
import { throttle } from 'lodash';
import isArray from 'lodash/isArray';
import { Checkbox, Form, Input, Select, Tabs } from 'antd';
import EditorToolbar from './EditorToolbar';
import Action from '../Button/Action';
import Body from '../Story/Body';
import './Editor.less';

const remarkable = new Remarkable();

const TabPane = Tabs.TabPane;

class Editor extends React.Component {
  static propTypes = {
    form: PropTypes.shape().isRequired,
    title: PropTypes.string,
    topics: PropTypes.arrayOf(PropTypes.string),
    body: PropTypes.string,
    reward: PropTypes.string,
    upvote: PropTypes.bool,
    loading: PropTypes.bool,
    onUpdate: PropTypes.func,
    onSubmit: PropTypes.func,
    onError: PropTypes.func,
    onImagePasted: PropTypes.func,
  };

  static defaultProps = {
    title: '',
    topics: [],
    body: '',
    reward: '50',
    upvote: true,
    recentTopics: [],
    popularTopics: [],
    loading: false,
    onUpdate: () => {},
    onSubmit: () => {},
    onError: () => {},
    onImagePasted: () => {},
  };

  static hotkeys = {
    h1: 'ctrl+shift+1',
    h2: 'ctrl+shift+2',
    h3: 'ctrl+shift+3',
    h4: 'ctrl+shift+4',
    h5: 'ctrl+shift+5',
    h6: 'ctrl+shift+6',
    bold: 'ctrl+b',
    italic: 'ctrl+i',
    quote: 'ctrl+q',
    link: 'ctrl+k',
    image: 'ctrl+m',
  };

  state = {
    contentHtml: '',
    noContent: false,
  };

  componentDidMount() {
    if (this.input) {
      this.input.addEventListener('input', throttle(e => this.renderMarkdown(e.target.value), 500));
      this.input.addEventListener('paste', this.handlePastedImage);
    }

    this.setValues(this.props);

    // eslint-disable-next-line react/no-find-dom-node
    const select = ReactDOM.findDOMNode(this.select);
    if (select) {
      const selectInput = select.querySelector('input,textarea,div[contentEditable]');
      if (selectInput) {
        selectInput.setAttribute('autocorrect', 'off');
        selectInput.setAttribute('autocapitalize', 'none');
      }
    }
  }

  componentWillReceiveProps(nextProps) {
    const { title, topics, body, reward, upvote } = this.props;
    if (
      title !== nextProps.title ||
      topics !== nextProps.topics ||
      body !== nextProps.body ||
      reward !== nextProps.reward ||
      upvote !== nextProps.upvote
    ) {
      this.setValues(nextProps);
    }
  }

  onUpdate = (e) => {
    // NOTE: antd doesn't update field value on Select before firing onChange
    // so we have to get value from event.
    this.props.onUpdate(this.getValues(e));
  };

  setInput = (input) => {
    if (input && input.refs && input.refs.input) {
      // eslint-disable-next-line react/no-find-dom-node
      this.input = ReactDOM.findDOMNode(input.refs.input);
    }
  };

  setValues = (post) => {
    this.props.form.setFieldsValue({
      title: post.title,
      topics: post.topics,
      reward: post.reward,
      upvote: post.upvote,
    });
    if (this.input) {
      this.input.value = post.body;
      this.renderMarkdown(this.input.value);
    }
  };

  getValues = (e) => {
    // NOTE: antd API is inconsistent and returns event or just value depending of input type.
    // this code extracts value from event based of event type
    // (array or just value for Select, proxy event for inputs and checkboxes)

    const values = {
      ...this.props.form.getFieldsValue(['title', 'topics', 'reward', 'upvote']),
      body: this.input.value,
    };

    if (!e) return values;

    if (isArray(e)) {
      values.topics = e;
    } else if (typeof e === 'string') {
      values.reward = e;
    } else if (e.target.type === 'textarea') {
      values.body = e.target.value;
    } else if (e.target.type === 'text') {
      values.title = e.target.value;
    } else if (e.target.type === 'checkbox') {
      values.upvote = e.target.checked;
    }
{'fraction_non_alphanumeric': 0.15413346613545817, 'fraction_numerical': 0.004233067729083665, 'mean_word_length': 2.814339981006648, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5903577', 'n_tokens_mistral': 2630, 'n_tokens_neox': 2611, 'n_words': 602}