<commit_before>import invariant from 'invariant';
import closest from 'dom-closest';
import removeNode from 'dom-remove';
import findWhere from 'lodash.findwhere';
import getKeyCode from './utils/getKeyCode';
import extractMentions from './utils/extractMentions';

import {
  collectMentionIds,
  getEditorContent,
  getLastChar,
} from './utils/tinyMCEUtils';

import {
  moveDown,
  moveUp,
  query,
  remove,
  resetMentions,
  resetQuery,
  select,
  syncEditorState
} from './actions/mentionActions';

const keyMap = {
  BACKSPACE: 8,
  DOWN: 40,
  ENTER: 13,
  TAB: 9,
  UP: 38,
  ESC: 27
};

const delimiters = ['@', '#'];

var delimiter = '@';
var editor;
var store;

const focus = {
  active: false,

  toggle() {
    this.active = !this.active;
    return this.active;
  }
};

/**
 * Tracks typed characters after `@ment|`.  Allows us to determine if we
 * are within a mention when `focus.active`
 */
const typedMention = {
   value: '',

   update(str) {
     this.value = (this.value + str).trim();
     return this.value;
   },
   backspace() {
     const val = this.value;
     this.value = val.substring(0, val.length - 1).trim();
     return this.value;
   },
   clear() {
     this.value = '';
   }
 };

export function initializePlugin(reduxStore, dataSource, delimiterValue) {

  if (typeof window.tinymce === 'undefined') {
    throw new Error('Error initializing Mention plugin: `tinymce` is undefined.');
  }

  return new Promise((resolve, reject) => {

    if (pluginInitialized()) {
      loadMentions(dataSource, resolve, reject);
    } else {
      window.tinymce.PluginManager.add('mention', (activeEditor) => {

        invariant(reduxStore,
          'Plugin must be initialized with a Redux store.'
        );

        invariant(dataSource,
          'Plugin must be initialized with a `dataSource` that is an array or promise.'
        );

        invariant(isValidDelimiter(delimiterValue),
          `Plugin must be initialized with a valid delimiter (${delimiters.toString()})`
        );

        store = reduxStore;
        delimiter = delimiterValue;
        editor = activeEditor;

        loadMentions(dataSource, resolve, reject);
      });
    }
  });
}

function loadMentions(dataSource, resolve) {
  if (typeof dataSource.then === 'function') {
    dataSource.then(response => {
      start();
      resolve({
        editor,
        resolvedDataSource: response
      });
    });

    if (dataSource.catch === 'function') {
      dataSource.catch(error => {
        throw new Error(error);
      });
    } else if (dataSource.fail === 'function') {
      dataSource.fail(error => {
        throw new Error(error);
      });
    }
  } else {
    start();
    resolve({
      editor,
      resolvedDataSource: dataSource
    });
  }
}

function start() {
  const delay = 100; // FireFox fix

  stop();
  setTimeout(() => {
    editor.on('keypress', handleTopLevelEditorInput);
    editor.on('keydown', handleTopLevelActionKeys);
    editor.on('keyup', handleBackspace);
  }, delay);
}

function stop() {
  editor.off();
}

function handleTopLevelEditorInput(event) {
  const keyCode = getKeyCode(event);
  const character = String.fromCharCode(keyCode);
  const foundDelimiter = delimiter.indexOf(character) > -1;

  normalizeEditorInput(editor);

  if (!focus.active && foundDelimiter) {
    startListeningForInput();
  } else if (!focus.active || character === ' ') {
    stopListeningAndCleanup();
  }
}

function handleTopLevelActionKeys(event) {
  const keyCode = getKeyCode(event);

  if (focus.active && keyCode === keyMap.BACKSPACE) {<commit_msg>Testing init regression<commit_after>import invariant from 'invariant';
import closest from 'dom-closest';
import removeNode from 'dom-remove';
import findWhere from 'lodash.findwhere';
import getKeyCode from './utils/getKeyCode';
import extractMentions from './utils/extractMentions';

import {
  collectMentionIds,
  getEditorContent,
  getLastChar,
} from './utils/tinyMCEUtils';

import {
  moveDown,
  moveUp,
  query,
  remove,
  resetMentions,
  resetQuery,
  select,
  syncEditorState
} from './actions/mentionActions';

const keyMap = {
  BACKSPACE: 8,
  DOWN: 40,
  ENTER: 13,
  TAB: 9,
  UP: 38,
  ESC: 27
};

const delimiters = ['@', '#'];

var delimiter = '@';
var editor;
var store;

const focus = {
  active: false,

  toggle() {
    this.active = !this.active;
    return this.active;
  }
};

/**
 * Tracks typed characters after `@ment|`.  Allows us to determine if we
 * are within a mention when `focus.active`
 */
const typedMention = {
   value: '',

   update(str) {
     this.value = (this.value + str).trim();
     return this.value;
   },
   backspace() {
     const val = this.value;
     this.value = val.substring(0, val.length - 1).trim();
     return this.value;
   },
   clear() {
     this.value = '';
   }
 };

export function initializePlugin(reduxStore, dataSource, delimiterValue) {

  if (typeof window.tinymce === 'undefined') {
    throw new Error('Error initializing Mention plugin: `tinymce` is undefined.');
  }

  return new Promise((resolve, reject) => {

    if (pluginInitialized()) {
      loadMentions(dataSource, resolve, reject);
    } else {
      window.tinymce.PluginManager.add('mention', (activeEditor) => {

        invariant(reduxStore,
          'Plugin must be initialized with a Redux store.'
        );

        invariant(dataSource,
          'Plugin must be initialized with a `dataSource` that is an array or promise.'
        );

        invariant(isValidDelimiter(delimiterValue),
          `Plugin must be initialized with a valid delimiter (${delimiters.toString()})`
        );

        store = reduxStore;
        delimiter = delimiterValue;
        editor = activeEditor;

        loadMentions(dataSource, resolve, reject);
      });
    }
  });
}

function loadMentions(dataSource, resolve) {
  if (typeof dataSource.then === 'function') {
    dataSource.then(response => {
      setTimeout(start, 100) //();
      resolve({
        editor,
        resolvedDataSource: response
      });
    });

    if (dataSource.catch === 'function') {
      dataSource.catch(error => {
        throw new Error(error);
      });
    } else if (dataSource.fail === 'function') {
      dataSource.fail(error => {
        throw new Error(error);
      });
    }
  } else {
    setTimeout(start, 100) //();
    resolve({
      editor,
      resolvedDataSource: dataSource
    });
  }
}

function start() {
  const delay = 100; // FireFox fix

  stop();
  // setTimeout(() => {
    editor.on('keypress', handleTopLevelEditorInput);
    editor.on('keydown', handleTopLevelActionKeys);
    editor.on('keyup', handleBackspace);
  // }, delay);
}

function stop() {
  editor.off();
}

function handleTopLevelEditorInput(event) {
  const keyCode = getKeyCode(event);
  const character = String.fromCharCode(keyCode);
  const foundDelimiter = delimiter.indexOf(character) > -1;

  normalizeEditorInput(editor);

  if (!focus.active && foundDelimiter) {
    startListeningForInput();
  } else if (!focus.active || character === ' ') {
    stopListeningAndCleanup();
  }
}

function handleTopLevelActionKeys(event) {
  const keyCode = getKeyCode(event);

  if (focus.active && keyCode === keyMap.BACKSPACE) {
{'fraction_non_alphanumeric': 0.13623827909542197, 'fraction_numerical': 0.005239933811362383, 'mean_word_length': 3.013835085777532, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 17, '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': '7621059', 'n_tokens_mistral': 2284, 'n_tokens_neox': 2220, 'n_words': 536}