<commit_before>import DEFAULTS from './defaults';
import TEMPLATE from './template';
import render from './render';
import preview from './preview';
import events from './events';
import handlers from './handlers';
import change from './change';
import methods from './methods';
import {
  ACTION_ALL,
  CLASS_HIDDEN,
  CLASS_HIDE,
  CLASS_INVISIBLE,
  CLASS_MOVE,
  DATA_ACTION,
  EVENT_READY,
  MIME_TYPE_JPEG,
  NAMESPACE,
  REGEXP_DATA_URL,
  REGEXP_DATA_URL_JPEG,
  REGEXP_TAG_NAME,
  WINDOW,
} from './constants';
import {
  addClass,
  addListener,
  addTimestamp,
  arrayBufferToDataURL,
  assign,
  dataURLToArrayBuffer,
  dispatchEvent,
  getOrientation,
  isCrossOriginURL,
  isFunction,
  isPlainObject,
  parseOrientation,
  removeClass,
  setData,
} from './utilities';

const AnotherCropper = WINDOW.Cropper;

class Cropper {
  /**
   * Create a new Cropper.
   * @param {Element} element - The target element for cropping.
   * @param {Object} [options={}] - The configuration options.
   */
  constructor(element, options = {}) {
    if (!element || !REGEXP_TAG_NAME.test(element.tagName)) {
      throw new Error('The first argument is required and must be an <img> or <canvas> element.');
    }

    this.element = element;
    this.options = assign({}, DEFAULTS, isPlainObject(options) && options);
    this.cropped = false;
    this.disabled = false;
    this.pointers = {};
    this.ready = false;
    this.reloading = false;
    this.replaced = false;
    this.sized = false;
    this.sizing = false;
    this.init();
  }

  init() {
    const { element } = this;
    const tagName = element.tagName.toLowerCase();
    let url;

    if (element[NAMESPACE]) {
      return;
    }

    element[NAMESPACE] = this;

    if (tagName === 'img') {
      this.isImg = true;

      // e.g.: "img/picture.jpg"
      url = element.getAttribute('src') || '';
      this.originalUrl = url;

      // Stop when it's a blank image
      if (!url) {
        return;
      }

      // e.g.: "http://example.com/img/picture.jpg"
      url = element.src;
    } else if (tagName === 'canvas' && window.HTMLCanvasElement) {
      url = element.toDataURL();
    }

    this.load(url);
  }

  load(url) {
    if (!url) {
      return;
    }

    this.url = url;
    this.imageData = {};

    const { element, options } = this;

    if (!options.rotatable && !options.scalable) {
      options.checkOrientation = false;
    }

    if (!options.checkOrientation || !window.ArrayBuffer) {
      this.clone();
      return;
    }

    // XMLHttpRequest disallows to open a Data URL in some browsers like IE11 and Safari
    if (REGEXP_DATA_URL.test(url)) {
      if (REGEXP_DATA_URL_JPEG.test(url)) {
        this.read(dataURLToArrayBuffer(url), true);
      } else {
        this.clone();
      }

      return;
    }

    const xhr = new XMLHttpRequest();
    const clone = this.clone.bind(this);

    this.reloading = true;
    this.xhr = xhr;
    xhr.ontimeout = clone;
    xhr.onabort = clone;
    xhr.onerror = clone;

    xhr.onprogress = () => {
      if (xhr.getResponseHeader('content-type') !== MIME_TYPE_JPEG) {
        xhr.abort();
      }
    };

    xhr.onload = () => {
      this.read(xhr.response);
    };

    xhr.onloadend = () => {
      this.reloading = false;
      this.xhr = null;
    };

    // Bust cache when there is a "crossOrigin" property
    if (options.checkCrossOrigin && isCrossOriginURL(url) && element.crossOrigin) {
      url = addTimestamp(url);
    }

    xhr.open('get', url);
    xhr.responseType = 'arraybuffer';
    xhr.withCredentials = element.crossOrigin === 'use-credentials';
    xhr.send();
  }

  read(arrayBuffer, isDataURL = false) {
    const { options, imageData } = this;
    const orientation = getOrientation(arrayBuffer);
    let rotate = 0;
    let scaleX = 1;
    let scaleY = 1;

    if (orientation > 1) {
      if (!isDataURL) {
        this.url = arrayBufferToDataURL(arrayBuffer, MIME_TYPE_JPEG);
      }

      ({ rotate, scaleX, scaleY } = parseOrientation(orientation));<commit_msg>docs: add reason for cache busting<commit_after>import DEFAULTS from './defaults';
import TEMPLATE from './template';
import render from './render';
import preview from './preview';
import events from './events';
import handlers from './handlers';
import change from './change';
import methods from './methods';
import {
  ACTION_ALL,
  CLASS_HIDDEN,
  CLASS_HIDE,
  CLASS_INVISIBLE,
  CLASS_MOVE,
  DATA_ACTION,
  EVENT_READY,
  MIME_TYPE_JPEG,
  NAMESPACE,
  REGEXP_DATA_URL,
  REGEXP_DATA_URL_JPEG,
  REGEXP_TAG_NAME,
  WINDOW,
} from './constants';
import {
  addClass,
  addListener,
  addTimestamp,
  arrayBufferToDataURL,
  assign,
  dataURLToArrayBuffer,
  dispatchEvent,
  getOrientation,
  isCrossOriginURL,
  isFunction,
  isPlainObject,
  parseOrientation,
  removeClass,
  setData,
} from './utilities';

const AnotherCropper = WINDOW.Cropper;

class Cropper {
  /**
   * Create a new Cropper.
   * @param {Element} element - The target element for cropping.
   * @param {Object} [options={}] - The configuration options.
   */
  constructor(element, options = {}) {
    if (!element || !REGEXP_TAG_NAME.test(element.tagName)) {
      throw new Error('The first argument is required and must be an <img> or <canvas> element.');
    }

    this.element = element;
    this.options = assign({}, DEFAULTS, isPlainObject(options) && options);
    this.cropped = false;
    this.disabled = false;
    this.pointers = {};
    this.ready = false;
    this.reloading = false;
    this.replaced = false;
    this.sized = false;
    this.sizing = false;
    this.init();
  }

  init() {
    const { element } = this;
    const tagName = element.tagName.toLowerCase();
    let url;

    if (element[NAMESPACE]) {
      return;
    }

    element[NAMESPACE] = this;

    if (tagName === 'img') {
      this.isImg = true;

      // e.g.: "img/picture.jpg"
      url = element.getAttribute('src') || '';
      this.originalUrl = url;

      // Stop when it's a blank image
      if (!url) {
        return;
      }

      // e.g.: "http://example.com/img/picture.jpg"
      url = element.src;
    } else if (tagName === 'canvas' && window.HTMLCanvasElement) {
      url = element.toDataURL();
    }

    this.load(url);
  }

  load(url) {
    if (!url) {
      return;
    }

    this.url = url;
    this.imageData = {};

    const { element, options } = this;

    if (!options.rotatable && !options.scalable) {
      options.checkOrientation = false;
    }

    if (!options.checkOrientation || !window.ArrayBuffer) {
      this.clone();
      return;
    }

    // XMLHttpRequest disallows to open a Data URL in some browsers like IE11 and Safari
    if (REGEXP_DATA_URL.test(url)) {
      if (REGEXP_DATA_URL_JPEG.test(url)) {
        this.read(dataURLToArrayBuffer(url), true);
      } else {
        this.clone();
      }

      return;
    }

    const xhr = new XMLHttpRequest();
    const clone = this.clone.bind(this);

    this.reloading = true;
    this.xhr = xhr;
    xhr.ontimeout = clone;
    xhr.onabort = clone;
    xhr.onerror = clone;

    xhr.onprogress = () => {
      if (xhr.getResponseHeader('content-type') !== MIME_TYPE_JPEG) {
        xhr.abort();
      }
    };

    xhr.onload = () => {
      this.read(xhr.response);
    };

    xhr.onloadend = () => {
      this.reloading = false;
      this.xhr = null;
    };

    // Bust cache when there is a "crossOrigin" property to avoid browser cache error
    if (options.checkCrossOrigin && isCrossOriginURL(url) && element.crossOrigin) {
      url = addTimestamp(url);
    }

    xhr.open('get', url);
    xhr.responseType = 'arraybuffer';
    xhr.withCredentials = element.crossOrigin === 'use-credentials';
    xhr.send();
  }

  read(arrayBuffer, isDataURL = false) {
    const { options, imageData } = this;
    const orientation = getOrientation(arrayBuffer);
    let rotate = 0;
    let scaleX = 1;
    let scaleY = 1;

    if (orientation > 1) {
      if (!isDataURL) {
        this.url = arrayBufferToDataURL(arrayBuffer, MIME_TYPE_JPEG);
      }

      ({ rotate, scaleX, scaleY } = parseOrientation(orientation));
{'fraction_non_alphanumeric': 0.1346673213847287, 'fraction_numerical': 0.0014731156395777069, 'mean_word_length': 2.62572318647085, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 15, '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': '303944', 'n_tokens_mistral': 2755, 'n_tokens_neox': 2662, 'n_words': 615}