<commit_before>
import { Editor, Mark, Raw, Utils } from '../..'
import React from 'react'
import initialState from './state.json'
import keycode from 'keycode'

/**
 * Define a set of node renderers.
 *
 * @type {Object}
 */

const NODES = {
  'block-quote': props => <blockquote {...props.attributes}>{props.children}</blockquote>,
  'bulleted-list': props => <ul {...props.attributes}>{props.children}</ul>,
  'heading-one': props => <h1 {...props.attributes}>{props.children}</h1>,
  'heading-two': props => <h2 {...props.attributes}>{props.children}</h2>,
  'list-item': props => <li {...props.attributes}>{props.children}</li>,
  'numbered-list': props => <ol {...props.attributes}>{props.children}</ol>
}

/**
 * Define a set of mark renderers.
 *
 * @type {Object}
 */

const MARKS = {
  bold: {
    fontWeight: 'bold'
  },
  code: {
    fontFamily: 'monospace',
    backgroundColor: '#eee',
    padding: '3px',
    borderRadius: '4px'
  },
  italic: {
    fontStyle: 'italic'
  },
  underlined: {
    textDecoration: 'underline'
  }
}

/**
 * The rich text example.
 *
 * @type {Component}
 */

class RichText extends React.Component {

  /**
   * Deserialize the initial editor state.
   *
   * @type {Object}
   */

  state = {
    state: Raw.deserialize(initialState)
  };

  /**
   * Check if the current selection has a mark with `type` in it.
   *
   * @param {String} type
   * @return {Boolean}
   */

  hasMark = (type) => {
    const { state } = this.state
    return state.marks.some(mark => mark.type == type)
  }

  /**
   * Check if the any of the currently selected blocks are of `type`.
   *
   * @param {String} type
   * @return {Boolean}
   */

  hasBlock = (type) => {
    const { state } = this.state
    return state.blocks.some(node => node.type == type)
  }

  /**
   * On change, save the new state.
   *
   * @param {State} state
   */

  onChange = (state) => {
    this.setState({ state })
  }

  /**
   * On key down, if it's a formatting command toggle a mark.
   *
   * @param {Event} e
   * @param {State} state
   * @return {State}
   */

  onKeyDown = (e, state) => {
    if (!Utils.Key.isCommand(e)) return
    const key = keycode(e.which)
    let mark

    switch (key) {
      case 'b':
        mark = 'bold'
        break
      case 'i':
        mark = 'italic'
        break
      case 'u':
        mark = 'underlined'
        break
      case '`':
        mark = 'code'
        break
      default:
        return
    }

    state = state
      .transform()
      [this.hasMark(mark) ? 'unmark' : 'mark'](mark)
      .apply()

    e.preventDefault()
    return state
  }

  /**
   * When a mark button is clicked, toggle the current mark.
   *
   * @param {Event} e
   * @param {String} type
   */

  onClickMark = (e, type) => {
    e.preventDefault()
    const isActive = this.hasMark(type)
    let { state } = this.state

    state = state
      .transform()
      [isActive ? 'unmark' : 'mark'](type)
      .apply()

    this.setState({ state })
  }

  /**
   * When a block button is clicked, toggle the block type.
   *
   * @param {Event} e
   * @param {String} type
   */

  onClickBlock = (e, type) => {
    e.preventDefault()
    const isActive = this.hasBlock(type)
    let { state } = this.state

    state = state
      .transform()
      .setBlock(isActive ? 'paragraph' : type)
      .apply()

    this.setState({ state })
  }

  /**
   * Render.
   *
   * @return {Element}
   */

  render = () => {
    return (
      <div>
        {this.renderToolbar()}<commit_msg>fix rich-text example lists<commit_after>
import { Editor, Mark, Raw, Utils } from '../..'
import React from 'react'
import initialState from './state.json'
import keycode from 'keycode'

/**
 * Define the default node type.
 */

const DEFAULT_NODE = 'paragraph'

/**
 * Define a set of node renderers.
 *
 * @type {Object}
 */

const NODES = {
  'block-quote': props => <blockquote {...props.attributes}>{props.children}</blockquote>,
  'bulleted-list': props => <ul {...props.attributes}>{props.children}</ul>,
  'heading-one': props => <h1 {...props.attributes}>{props.children}</h1>,
  'heading-two': props => <h2 {...props.attributes}>{props.children}</h2>,
  'list-item': props => <li {...props.attributes}>{props.children}</li>,
  'numbered-list': props => <ol {...props.attributes}>{props.children}</ol>
}

/**
 * Define a set of mark renderers.
 *
 * @type {Object}
 */

const MARKS = {
  bold: {
    fontWeight: 'bold'
  },
  code: {
    fontFamily: 'monospace',
    backgroundColor: '#eee',
    padding: '3px',
    borderRadius: '4px'
  },
  italic: {
    fontStyle: 'italic'
  },
  underlined: {
    textDecoration: 'underline'
  }
}

/**
 * The rich text example.
 *
 * @type {Component}
 */

class RichText extends React.Component {

  /**
   * Deserialize the initial editor state.
   *
   * @type {Object}
   */

  state = {
    state: Raw.deserialize(initialState)
  };

  /**
   * Check if the current selection has a mark with `type` in it.
   *
   * @param {String} type
   * @return {Boolean}
   */

  hasMark = (type) => {
    const { state } = this.state
    return state.marks.some(mark => mark.type == type)
  }

  /**
   * Check if the any of the currently selected blocks are of `type`.
   *
   * @param {String} type
   * @return {Boolean}
   */

  hasBlock = (type) => {
    const { state } = this.state
    return state.blocks.some(node => node.type == type)
  }

  /**
   * On change, save the new state.
   *
   * @param {State} state
   */

  onChange = (state) => {
    this.setState({ state })
  }

  /**
   * On key down, if it's a formatting command toggle a mark.
   *
   * @param {Event} e
   * @param {State} state
   * @return {State}
   */

  onKeyDown = (e, state) => {
    if (!Utils.Key.isCommand(e)) return
    const key = keycode(e.which)
    let mark

    switch (key) {
      case 'b':
        mark = 'bold'
        break
      case 'i':
        mark = 'italic'
        break
      case 'u':
        mark = 'underlined'
        break
      case '`':
        mark = 'code'
        break
      default:
        return
    }

    state = state
      .transform()
      [this.hasMark(mark) ? 'unmark' : 'mark'](mark)
      .apply()

    e.preventDefault()
    return state
  }

  /**
   * When a mark button is clicked, toggle the current mark.
   *
   * @param {Event} e
   * @param {String} type
   */

  onClickMark = (e, type) => {
    e.preventDefault()
    const isActive = this.hasMark(type)
    let { state } = this.state

    state = state
      .transform()
      [isActive ? 'unmark' : 'mark'](type)
      .apply()

    this.setState({ state })
  }

  /**
   * When a block button is clicked, toggle the block type.
   *
   * @param {Event} e
   * @param {String} type
   */

  onClickBlock = (e, type) => {
    e.preventDefault()
    const isActive = this.hasBlock(type)
    let { state } = this.state

    let transform = state
      .transform()
      .setBlock(isActive ? 'paragraph' : type)

    // Handle the extra wrapping required for list buttons.
    if (type == 'bulleted-list' || type == 'numbered-list') {
      if (this.hasBlock('list-item')) {
        transform = transform
          .setBlock(DEFAULT_NODE)
          .unwrapBlock(type)
      } else {
        transform = transform
          .setBlock('list-item')
          .wrapBlock(type)
      }
    }

    // Handle everything but list buttons.
    else {
      transform = transform.setBlock(isActive ? DEFAULT_NODE : type)
    }

    state = transform.apply()
    this.setState({ state })
  }

  /**
   * Render.
   *
   * @return {Element}
   */

  render = () => {
    return (
      <div>
        {this.renderToolbar()}
{'fraction_non_alphanumeric': 0.16206717000781046, 'fraction_numerical': 0.0015620932048945586, 'mean_word_length': 2.1972534332084894, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 59, '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': '4482836', 'n_tokens_mistral': 2591, 'n_tokens_neox': 2558, 'n_words': 658}