<commit_before>import * as React from 'react';
import { debounce } from 'lodash';
import PropTypes from 'prop-types';

export default class TextEllipsis extends React.Component {
  constructor(props) {
    super(props);

    this.isSupportNativeClamp = this.props.useJsOnly ? false : 'webkitLineClamp' in document.body.style;
    this.truncate = this.truncate.bind(this);
    this.throttleProcess = debounce(this.process, this.props.debounceTimeoutOnResize);
  }

  componentDidMount() {
    this.text = this.container.innerHTML;

    this.process();

    window.addEventListener('resize', this.throttleProcess, false);
  }

  componentDidUpdate() {
    this.process();
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.throttleProcess, false);
  }

  getTextWithEllipsis(start, end) {
    this.currentText = this.text.slice(start, end);
    return this.currentText + this.props.ellipsisChars;
  }

  getLineHeight() {
    const lineHeight = this.computedStyle("line-height");

    if (lineHeight === 'normal') {
      // Normal line heights vary from browser to browser. The spec recommends
      // a value between 1.0 and 1.2 of the font size. Using 1.1 to split the diff.
      return Math.ceil(parseFloat(this.computedStyle('font-size')) * 1.2);
    }
    return Math.ceil(parseFloat(lineHeight));
  }

  populateIsTuncated() {
    if (this.props.isTruncated && (elem.scrollWidth > elem.clientWidth || elem.scrollHeight > elem.clientHeight)) {
      this.props.isTruncated();
    }
  }

  truncate() {
    if (this.container.offsetHeight > this.lineHeight * this.props.lines) {
      this.container.innerHTML = this.getTextWithEllipsis(0, this.end - 1);
      this.props.isTruncated && this.props.isTruncated();
    } else if (this.end >= this.textLength) {
      this.container.innerHTML = this.currentText;
    } else {
      this.container.innerHTML = this.getTextWithEllipsis(this.start, ++this.end);
      this.truncate();
    }
  }

  process() {
    if (this.isSupportNativeClamp) {
      const sty = this.container.style;
      sty.overflow = 'hidden';
      sty.textOverflow = 'ellipsis';
      sty.webkitBoxOrient = 'vertical';
      sty.display = '-webkit-box';
      sty.webkitLineClamp = this.props.lines;

      this.container.innerHTML = this.text;
      this.populateIsTuncated();
    } else {
      this.textLength = this.text.length;
      this.currentText = '';
      this.start = 0;
      this.end = this.text.length > 0 ? 1 : 0;
      this.lineHeight = this.getLineHeight();
      this.container.innerHTML = '';

      this.truncate();
    }
  }

  computedStyle(name) {
    return document.defaultView.getComputedStyle(this.container, null).getPropertyValue(name);
  }

  render() {
    return (
      React.createElement(this.props.tag, {
          ref: (node) => {
            this.container = node;
          },
          className: this.props.tagClass ? this.props.tagClass : '',
          style: { 'width': '100%', 'word-wrap': 'break-word' },
        },
        this.props.children,
      )
    );
  }
}

TextEllipsis.propTypes = {
  lines: PropTypes.number.isRequired,
  children: PropTypes.element.isRequired,
  tag: PropTypes.string,
  ellipsisChars: PropTypes.string,
  tagClass: PropTypes.string,
  debounceTimeoutOnResize: PropTypes.number,
  useJsOnly: PropTypes.bool,
  isTruncated: PropTypes.func,
};

TextEllipsis.defaultProps = {
  tag: 'div',
  ellipsisChars: '...',
  tagClass: '',
  debounceTimeoutOnResize: 200,
  useJsOnly: false,
  isTruncated: null,
};<commit_msg>replace isTruncated props with onResult props #5<commit_after>import * as React from 'react';
import { debounce } from 'lodash';
import PropTypes from 'prop-types';

class TextEllipsis extends React.Component {
  constructor(props) {
    super(props);

    this.isSupportNativeClamp = this.props.useJsOnly ? false : 'webkitLineClamp' in document.body.style;
    this.truncate = this.truncate.bind(this);
    this.debounceProcess = debounce(this.process, this.props.debounceTimeoutOnResize);
  }

  componentDidMount() {
    this.text = this.container.innerHTML;
    this.process();

    window.addEventListener('resize', this.debounceProcess, false);
  }

  componentDidUpdate() {
    this.process();
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.debounceProcess, false);
  }

  onResult() {
    if (elem.scrollWidth > elem.clientWidth || elem.scrollHeight > elem.clientHeight) {
      this.props.onResult(TextEllipsis.RESULT.TRUNCATED);
    } else {
      this.props.onResult(TextEllipsis.RESULT.NOT_TRUNCATED);
    }
  }

  getLineHeight() {
    const lineHeight = this.computedStyle("line-height");

    if (lineHeight === 'normal') {
      // Normal line heights vary from browser to browser. The spec recommends
      // a value between 1.0 and 1.2 of the font size. Using 1.1 to split the diff.
      return Math.ceil(parseFloat(this.computedStyle('font-size')) * 1.2);
    }
    return Math.ceil(parseFloat(lineHeight));
  }

  getTextWithEllipsis(start, end) {
    this.currentText = this.text.slice(start, end);
    return this.currentText + this.props.ellipsisChars;
  }

  truncate() {
    if (this.container.offsetHeight > this.lineHeight * this.props.lines) {
      this.container.innerHTML = this.getTextWithEllipsis(0, this.end - 1);
      this.onResult();
    } else if (this.end >= this.textLength) {
      this.container.innerHTML = this.currentText;
      this.onResult();
    } else {
      this.container.innerHTML = this.getTextWithEllipsis(this.start, ++this.end);
      this.truncate();
    }
  }

  process() {
    if (this.isSupportNativeClamp) {
      const sty = this.container.style;
      sty.overflow = 'hidden';
      sty.textOverflow = 'ellipsis';
      sty.webkitBoxOrient = 'vertical';
      sty.display = '-webkit-box';
      sty.webkitLineClamp = this.props.lines;

      this.container.innerHTML = this.text;
      this.populateIsTuncated();
    } else {
      this.textLength = this.text.length;
      this.currentText = '';
      this.start = 0;
      this.end = this.text.length > 0 ? 1 : 0;
      this.lineHeight = this.getLineHeight();
      this.container.innerHTML = '';

      this.truncate();
    }
  }

  computedStyle(name) {
    return document.defaultView.getComputedStyle(this.container, null).getPropertyValue(name);
  }

  render() {
    return (
      React.createElement(this.props.tag, {
          ref: (node) => {
            this.container = node;
          },
          className: this.props.tagClass,
          style: { 'width': '100%', 'word-wrap': 'break-word' },
        },
        this.props.children,
      )
    );
  }
}

TextEllipsis.RESULT = {
  TRUNCATED: "TRUNCATED",
  NOT_TRUNCATED: "NOT_TRUNCATED",
};

TextEllipsis.propTypes = {
  lines: PropTypes.number.isRequired,
  children: PropTypes.element.isRequired,
  tag: PropTypes.string,
  ellipsisChars: PropTypes.string,
  tagClass: PropTypes.string,
  debounceTimeoutOnResize: PropTypes.number,
  useJsOnly: PropTypes.bool,
  onResult: PropTypes.func,
};

TextEllipsis.defaultProps = {
  tag: 'div',
  ellipsisChars: '...',
  tagClass: '',
  debounceTimeoutOnResize: 200,
  useJsOnly: false,
  onResult: () => {},
};
{'fraction_non_alphanumeric': 0.1338877338877339, 'fraction_numerical': 0.005682605682605682, 'mean_word_length': 3.0653521126760563, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 16, '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': '2915059', 'n_tokens_mistral': 2375, 'n_tokens_neox': 2291, 'n_words': 416}