<commit_before>import {Plugin, PluginKey, TextSelection, EditorState, Transaction} from "prosemirror-state"
import {Step, Transform} from "prosemirror-transform"

class Rebaseable {
  constructor(
    readonly step: Step,
    readonly inverted: Step,
    readonly origin: Transform
  ) {}
}

/// Undo a given set of steps, apply a set of other steps, and then
/// redo them @internal
export function rebaseSteps(steps: readonly Rebaseable[], over: readonly Step[], transform: Transform) {
  for (let i = steps.length - 1; i >= 0; i--) transform.step(steps[i].inverted)
  for (let i = 0; i < over.length; i++) transform.step(over[i])
  let result = []
  for (let i = 0, mapFrom = steps.length; i < steps.length; i++) {
    let mapped = steps[i].step.map(transform.mapping.slice(mapFrom))
    mapFrom--
    if (mapped && !transform.maybeStep(mapped).failed) {
      transform.mapping.setMirror(mapFrom, transform.steps.length - 1)
      result.push(new Rebaseable(mapped, mapped.invert(transform.docs[transform.docs.length - 1]), steps[i].origin))
    }
  }
  return result
}

// This state field accumulates changes that have to be sent to the
// central authority in the collaborating group and makes it possible
// to integrate changes made by peers into our local document. It is
// defined by the plugin, and will be available as the `collab` field
// in the resulting editor state.
class CollabState {
  constructor(
    // The version number of the last update received from the central
    // authority. Starts at 0 or the value of the `version` property
    // in the option object, for the editor's value when the option
    // was enabled.
    readonly version: number,
    // The local steps that havent been successfully sent to the
    // server yet.
    readonly unconfirmed: readonly Rebaseable[]
  ) {}
}

function unconfirmedFrom(transform: Transform) {
  let result = []
  for (let i = 0; i < transform.steps.length; i++)
    result.push(new Rebaseable(transform.steps[i],
                               transform.steps[i].invert(transform.docs[i]),
                               transform))
  return result
}

const collabKey = new PluginKey("collab")

type CollabConfig = {
  /// The starting version number of the collaborative editing.
  /// Defaults to 0.
  version?: number

  /// This client's ID, used to distinguish its changes from those of
  /// other clients. Defaults to a random 32-bit number.
  clientID?: number | string
}

/// Creates a plugin that enables the collaborative editing framework
/// for the editor.
export function collab(config: CollabConfig = {}) {
  let conf: Required<CollabConfig> = {
    version: config.version || 0,
    clientID: config.clientID == null ? Math.floor(Math.random() * 0xFFFFFFFF) : config.clientID
  }

  return new Plugin({
    key: collabKey,

    state: {
      init: () => new CollabState(conf.version, []),
      apply(tr, collab) {
        let newState = tr.getMeta(collabKey)
        if (newState)
          return newState
        if (tr.docChanged)
          return new CollabState(collab.version, collab.unconfirmed.concat(unconfirmedFrom(tr)))
        return collab
      }
    },

    // @ts-ignore
    config: conf,

    // This is used to notify the history plugin to not merge steps,
    // so that the history can be rebased.
    historyPreserveItems: true
  })
}

/// Create a transaction that represents a set of new steps received from
/// the authority. Applying this transaction moves the state forward to
/// adjust to the authority's view of the document.
export function receiveTransaction(
  state: EditorState,
  steps: readonly Step[],
  clientIDs: readonly (string | number)[],
  options: {
    /// When enabled (the default is `false`), if the current
    /// selection is a [text selection](#state.TextSelection), its
    /// sides are mapped with a negative bias for this transaction, so
    /// that content inserted at the cursor ends up after the cursor.
    /// Users usually prefer this, but it isn't done by default for
    /// reasons of backwards compatibility.
    mapSelectionBackward?: boolean
  } = {}<commit_msg>Add explicit return type for plugin function<commit_after>import {Plugin, PluginKey, TextSelection, EditorState, Transaction} from "prosemirror-state"
import {Step, Transform} from "prosemirror-transform"

class Rebaseable {
  constructor(
    readonly step: Step,
    readonly inverted: Step,
    readonly origin: Transform
  ) {}
}

/// Undo a given set of steps, apply a set of other steps, and then
/// redo them @internal
export function rebaseSteps(steps: readonly Rebaseable[], over: readonly Step[], transform: Transform) {
  for (let i = steps.length - 1; i >= 0; i--) transform.step(steps[i].inverted)
  for (let i = 0; i < over.length; i++) transform.step(over[i])
  let result = []
  for (let i = 0, mapFrom = steps.length; i < steps.length; i++) {
    let mapped = steps[i].step.map(transform.mapping.slice(mapFrom))
    mapFrom--
    if (mapped && !transform.maybeStep(mapped).failed) {
      transform.mapping.setMirror(mapFrom, transform.steps.length - 1)
      result.push(new Rebaseable(mapped, mapped.invert(transform.docs[transform.docs.length - 1]), steps[i].origin))
    }
  }
  return result
}

// This state field accumulates changes that have to be sent to the
// central authority in the collaborating group and makes it possible
// to integrate changes made by peers into our local document. It is
// defined by the plugin, and will be available as the `collab` field
// in the resulting editor state.
class CollabState {
  constructor(
    // The version number of the last update received from the central
    // authority. Starts at 0 or the value of the `version` property
    // in the option object, for the editor's value when the option
    // was enabled.
    readonly version: number,
    // The local steps that havent been successfully sent to the
    // server yet.
    readonly unconfirmed: readonly Rebaseable[]
  ) {}
}

function unconfirmedFrom(transform: Transform) {
  let result = []
  for (let i = 0; i < transform.steps.length; i++)
    result.push(new Rebaseable(transform.steps[i],
                               transform.steps[i].invert(transform.docs[i]),
                               transform))
  return result
}

const collabKey = new PluginKey("collab")

type CollabConfig = {
  /// The starting version number of the collaborative editing.
  /// Defaults to 0.
  version?: number

  /// This client's ID, used to distinguish its changes from those of
  /// other clients. Defaults to a random 32-bit number.
  clientID?: number | string
}

/// Creates a plugin that enables the collaborative editing framework
/// for the editor.
export function collab(config: CollabConfig = {}): Plugin {
  let conf: Required<CollabConfig> = {
    version: config.version || 0,
    clientID: config.clientID == null ? Math.floor(Math.random() * 0xFFFFFFFF) : config.clientID
  }

  return new Plugin({
    key: collabKey,

    state: {
      init: () => new CollabState(conf.version, []),
      apply(tr, collab) {
        let newState = tr.getMeta(collabKey)
        if (newState)
          return newState
        if (tr.docChanged)
          return new CollabState(collab.version, collab.unconfirmed.concat(unconfirmedFrom(tr)))
        return collab
      }
    },

    config: conf,

    // This is used to notify the history plugin to not merge steps,
    // so that the history can be rebased.
    historyPreserveItems: true
  })
}

/// Create a transaction that represents a set of new steps received from
/// the authority. Applying this transaction moves the state forward to
/// adjust to the authority's view of the document.
export function receiveTransaction(
  state: EditorState,
  steps: readonly Step[],
  clientIDs: readonly (string | number)[],
  options: {
    /// When enabled (the default is `false`), if the current
    /// selection is a [text selection](#state.TextSelection), its
    /// sides are mapped with a negative bias for this transaction, so
    /// that content inserted at the cursor ends up after the cursor.
    /// Users usually prefer this, but it isn't done by default for
    /// reasons of backwards compatibility.
    mapSelectionBackward?: boolean
  } = {}
{'fraction_non_alphanumeric': 0.10402319681043856, 'fraction_numerical': 0.0031412347468889696, 'mean_word_length': 3.0360799609946367, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, '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': '3545780', 'n_tokens_mistral': 2335, 'n_tokens_neox': 2262, 'n_words': 884}