tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

step.ts (4015B)


      1 import {ReplaceError, Schema, Slice, Node} from "prosemirror-model"
      2 
      3 import {StepMap, Mappable} from "./map"
      4 
      5 const stepsByID: {[id: string]: {fromJSON(schema: Schema, json: any): Step}} = Object.create(null)
      6 
      7 /// A step object represents an atomic change. It generally applies
      8 /// only to the document it was created for, since the positions
      9 /// stored in it will only make sense for that document.
     10 ///
     11 /// New steps are defined by creating classes that extend `Step`,
     12 /// overriding the `apply`, `invert`, `map`, `getMap` and `fromJSON`
     13 /// methods, and registering your class with a unique
     14 /// JSON-serialization identifier using
     15 /// [`Step.jsonID`](#transform.Step^jsonID).
     16 export abstract class Step {
     17  /// Applies this step to the given document, returning a result
     18  /// object that either indicates failure, if the step can not be
     19  /// applied to this document, or indicates success by containing a
     20  /// transformed document.
     21  abstract apply(doc: Node): StepResult
     22 
     23  /// Get the step map that represents the changes made by this step,
     24  /// and which can be used to transform between positions in the old
     25  /// and the new document.
     26  getMap(): StepMap { return StepMap.empty }
     27 
     28  /// Create an inverted version of this step. Needs the document as it
     29  /// was before the step as argument.
     30  abstract invert(doc: Node): Step
     31 
     32  /// Map this step through a mappable thing, returning either a
     33  /// version of that step with its positions adjusted, or `null` if
     34  /// the step was entirely deleted by the mapping.
     35  abstract map(mapping: Mappable): Step | null
     36 
     37  /// Try to merge this step with another one, to be applied directly
     38  /// after it. Returns the merged step when possible, null if the
     39  /// steps can't be merged.
     40  merge(other: Step): Step | null { return null }
     41 
     42  /// Create a JSON-serializeable representation of this step. When
     43  /// defining this for a custom subclass, make sure the result object
     44  /// includes the step type's [JSON id](#transform.Step^jsonID) under
     45  /// the `stepType` property.
     46  abstract toJSON(): any
     47 
     48  /// Deserialize a step from its JSON representation. Will call
     49  /// through to the step class' own implementation of this method.
     50  static fromJSON(schema: Schema, json: any): Step {
     51    if (!json || !json.stepType) throw new RangeError("Invalid input for Step.fromJSON")
     52    let type = stepsByID[json.stepType]
     53    if (!type) throw new RangeError(`No step type ${json.stepType} defined`)
     54    return type.fromJSON(schema, json)
     55  }
     56 
     57  /// To be able to serialize steps to JSON, each step needs a string
     58  /// ID to attach to its JSON representation. Use this method to
     59  /// register an ID for your step classes. Try to pick something
     60  /// that's unlikely to clash with steps from other modules.
     61  static jsonID(id: string, stepClass: {fromJSON(schema: Schema, json: any): Step}) {
     62    if (id in stepsByID) throw new RangeError("Duplicate use of step JSON ID " + id)
     63    stepsByID[id] = stepClass
     64    ;(stepClass as any).prototype.jsonID = id
     65    return stepClass
     66  }
     67 }
     68 
     69 /// The result of [applying](#transform.Step.apply) a step. Contains either a
     70 /// new document or a failure value.
     71 export class StepResult {
     72  /// @internal
     73  constructor(
     74    /// The transformed document, if successful.
     75    readonly doc: Node | null,
     76    /// The failure message, if unsuccessful.
     77    readonly failed: string | null
     78  ) {}
     79 
     80  /// Create a successful step result.
     81  static ok(doc: Node) { return new StepResult(doc, null) }
     82 
     83  /// Create a failed step result.
     84  static fail(message: string) { return new StepResult(null, message) }
     85 
     86  /// Call [`Node.replace`](#model.Node.replace) with the given
     87  /// arguments. Create a successful result if it succeeds, and a
     88  /// failed one if it throws a `ReplaceError`.
     89  static fromReplace(doc: Node, from: number, to: number, slice: Slice) {
     90    try {
     91      return StepResult.ok(doc.replace(from, to, slice))
     92    } catch (e) {
     93      if (e instanceof ReplaceError) return StepResult.fail(e.message)
     94      throw e
     95    }
     96  }
     97 }