<commit_before>import * as actions from 'store/actions'
import assign from 'lodash/assign'
import forEach from 'lodash/forEach'
import humanFormat from 'human-format'
import includes from 'lodash/includes'
import isArray from 'lodash/isArray'
import isFunction from 'lodash/isFunction'
import isPlainObject from 'lodash/isPlainObject'
import isString from 'lodash/isString'
import map from 'lodash/map'
import mapValues from 'lodash/mapValues'
import pick from 'lodash/fp/pick'
import React, { cloneElement, PropTypes } from 'react'
import { connect } from 'react-redux'

import invoke from './invoke'

// ===================================================================

export const EMPTY_OBJECT = Object.freeze({ })

export const ensureArray = (value) => {
  if (value === undefined) {
    return []
  }

  return Array.isArray(value) ? value : [ value ]
}

export const propsEqual = (o1, o2, props) => {
  props = ensureArray(props)

  for (const prop of props) {
    if (o1[prop] !== o2[prop]) {
      return false
    }
  }

  return true
}

// ===================================================================

const _bind = (fn, thisArg) => function bound () {
  return fn.apply(thisArg, arguments)
}
const _defineProperty = Object.defineProperty

export const autobind = (target, key, {
  configurable,
  enumerable,
  value: fn,
  writable
}) => ({
  configurable,
  enumerable,

  get () {
    if (this === target) {
      return fn
    }

    const bound = _bind(fn, this)

    _defineProperty(this, key, {
      configurable: true,
      enumerable: false,
      value: bound,
      writable: true
    })

    return bound
  },
  set (newValue) {
    // Cannot use assignment because it will call the setter on
    // the prototype.
    _defineProperty(this, key, {
      configurable: true,
      enumerable: true,
      value: newValue,
      writable: true
    })
  }
})

// -------------------------------------------------------------------

export class BlockLink extends React.Component {
  static contextTypes = {
    router: React.PropTypes.object
  }

  render () {
    const { children } = this.props
    return (
      <div
        style={{
          cursor: 'pointer'
        }}
        onClickCapture={event => {
          const { currentTarget } = event
          let element = event.target
          while (element !== currentTarget) {
            if (includes(['A', 'INPUT', 'BUTTON'], element.tagName)) {
              return
            }
            element = element.parentNode
          }
          event.stopPropagation()
          this.context.router.push(this.props.to)
        }}
      >
        {children}
      </div>
    )
  }
}

// -------------------------------------------------------------------

const _normalizeMapStateToProps = mapper => {
  if (isFunction(mapper)) {
    return mapper
  }

  if (isArray(mapper)) {
    return pick(mapper)
  }

  mapper = mapValues(mapper, _normalizeMapStateToProps)
  return (state, props) => mapValues(mapper, fn => fn(state, props))
}

export const connectStore = (mapStateToProps, opts) => connect(
  _normalizeMapStateToProps(mapStateToProps),
  actions,
  undefined,
  opts
)

// -------------------------------------------------------------------

// Simple matcher to use in object filtering.<commit_msg>feat(utils/@checkPropsState): create an optimized shouldComponentUpdate()<commit_after>import * as actions from 'store/actions'
import assign from 'lodash/assign'
import forEach from 'lodash/forEach'
import humanFormat from 'human-format'
import includes from 'lodash/includes'
import isArray from 'lodash/isArray'
import isFunction from 'lodash/isFunction'
import isPlainObject from 'lodash/isPlainObject'
import isString from 'lodash/isString'
import map from 'lodash/map'
import mapValues from 'lodash/mapValues'
import pick from 'lodash/fp/pick'
import React, { cloneElement, PropTypes } from 'react'
import { connect } from 'react-redux'

import invoke from './invoke'

// ===================================================================

export const EMPTY_OBJECT = Object.freeze({ })

export const ensureArray = (value) => {
  if (value === undefined) {
    return []
  }

  return Array.isArray(value) ? value : [ value ]
}

export const propsEqual = (o1, o2, props) => {
  props = ensureArray(props)

  for (const prop of props) {
    if (o1[prop] !== o2[prop]) {
      return false
    }
  }

  return true
}

// ===================================================================

const _bind = (fn, thisArg) => function bound () {
  return fn.apply(thisArg, arguments)
}
const _defineProperty = Object.defineProperty

export const autobind = (target, key, {
  configurable,
  enumerable,
  value: fn,
  writable
}) => ({
  configurable,
  enumerable,

  get () {
    if (this === target) {
      return fn
    }

    const bound = _bind(fn, this)

    _defineProperty(this, key, {
      configurable: true,
      enumerable: false,
      value: bound,
      writable: true
    })

    return bound
  },
  set (newValue) {
    // Cannot use assignment because it will call the setter on
    // the prototype.
    _defineProperty(this, key, {
      configurable: true,
      enumerable: true,
      value: newValue,
      writable: true
    })
  }
})

// -------------------------------------------------------------------

export class BlockLink extends React.Component {
  static contextTypes = {
    router: React.PropTypes.object
  }

  render () {
    const { children } = this.props
    return (
      <div
        style={{
          cursor: 'pointer'
        }}
        onClickCapture={event => {
          const { currentTarget } = event
          let element = event.target
          while (element !== currentTarget) {
            if (includes(['A', 'INPUT', 'BUTTON'], element.tagName)) {
              return
            }
            element = element.parentNode
          }
          event.stopPropagation()
          this.context.router.push(this.props.to)
        }}
      >
        {children}
      </div>
    )
  }
}

// -------------------------------------------------------------------

export const checkPropsState = (propsNames, stateNames) => Component => {
  const nProps = propsNames && propsNames.length
  const nState = stateNames && stateNames.length

  Component.prototype.shouldComponentUpdate = (newProps, newState) => {
    const { props, state } = this

    for (let i = 0; i < nProps; ++i) {
      const name = propsNames[i]
      if (newProps[name] !== props[name]) {
        return true
      }
    }

    for (let i = 0; i < nState; ++i) {
      const name = stateNames[i]
      if (newState[name] !== state[name]) {
        return true
      }
    }
  }

  return Component
}

// -------------------------------------------------------------------

const _normalizeMapStateToProps = mapper => {
  if (isFunction(mapper)) {
    return mapper
  }

  if (isArray(mapper)) {
    return pick(mapper)
  }

  mapper = mapValues(mapper, _normalizeMapStateToProps)
  return (state, props) => mapValues(mapper, fn => fn(state, props))
}

export const connectStore = (mapStateToProps, opts) => connect(
  _normalizeMapStateToProps(mapStateToProps),
  actions,
  undefined,
  opts
)

// -------------------------------------------------------------------

// Simple matcher to use in object filtering.
{'fraction_non_alphanumeric': 0.2059384363933533, 'fraction_numerical': 0.001362026695723236, 'mean_word_length': 2.226274165202109, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 28, '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': '7444762', 'n_tokens_mistral': 2109, 'n_tokens_neox': 2058, 'n_words': 552}