259 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			259 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
import { isPlainObject } from 'is-plain-object';
 | 
						|
import { Operation, Editor, Path } from 'slate';
 | 
						|
 | 
						|
var History = {
 | 
						|
  /**
 | 
						|
   * Check if a value is a `History` object.
 | 
						|
   */
 | 
						|
  isHistory(value) {
 | 
						|
    return isPlainObject(value) && Array.isArray(value.redos) && Array.isArray(value.undos) && (value.redos.length === 0 || Operation.isOperationList(value.redos[0])) && (value.undos.length === 0 || Operation.isOperationList(value.undos[0]));
 | 
						|
  }
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * Weakmaps for attaching state to the editor.
 | 
						|
 */
 | 
						|
 | 
						|
var HISTORY = new WeakMap();
 | 
						|
var SAVING = new WeakMap();
 | 
						|
var MERGING = new WeakMap();
 | 
						|
var HistoryEditor = {
 | 
						|
  /**
 | 
						|
   * Check if a value is a `HistoryEditor` object.
 | 
						|
   */
 | 
						|
  isHistoryEditor(value) {
 | 
						|
    return History.isHistory(value.history) && Editor.isEditor(value);
 | 
						|
  },
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the merge flag's current value.
 | 
						|
   */
 | 
						|
  isMerging(editor) {
 | 
						|
    return MERGING.get(editor);
 | 
						|
  },
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the saving flag's current value.
 | 
						|
   */
 | 
						|
  isSaving(editor) {
 | 
						|
    return SAVING.get(editor);
 | 
						|
  },
 | 
						|
 | 
						|
  /**
 | 
						|
   * Redo to the previous saved state.
 | 
						|
   */
 | 
						|
  redo(editor) {
 | 
						|
    editor.redo();
 | 
						|
  },
 | 
						|
 | 
						|
  /**
 | 
						|
   * Undo to the previous saved state.
 | 
						|
   */
 | 
						|
  undo(editor) {
 | 
						|
    editor.undo();
 | 
						|
  },
 | 
						|
 | 
						|
  /**
 | 
						|
   * Apply a series of changes inside a synchronous `fn`, without merging any of
 | 
						|
   * the new operations into previous save point in the history.
 | 
						|
   */
 | 
						|
  withoutMerging(editor, fn) {
 | 
						|
    var prev = HistoryEditor.isMerging(editor);
 | 
						|
    MERGING.set(editor, false);
 | 
						|
    fn();
 | 
						|
    MERGING.set(editor, prev);
 | 
						|
  },
 | 
						|
 | 
						|
  /**
 | 
						|
   * Apply a series of changes inside a synchronous `fn`, without saving any of
 | 
						|
   * their operations into the history.
 | 
						|
   */
 | 
						|
  withoutSaving(editor, fn) {
 | 
						|
    var prev = HistoryEditor.isSaving(editor);
 | 
						|
    SAVING.set(editor, false);
 | 
						|
    fn();
 | 
						|
    SAVING.set(editor, prev);
 | 
						|
  }
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * The `withHistory` plugin keeps track of the operation history of a Slate
 | 
						|
 * editor as operations are applied to it, using undo and redo stacks.
 | 
						|
 *
 | 
						|
 * If you are using TypeScript, you must extend Slate's CustomTypes to use
 | 
						|
 * this plugin.
 | 
						|
 *
 | 
						|
 * See https://docs.slatejs.org/concepts/11-typescript to learn how.
 | 
						|
 */
 | 
						|
 | 
						|
var withHistory = editor => {
 | 
						|
  var e = editor;
 | 
						|
  var {
 | 
						|
    apply
 | 
						|
  } = e;
 | 
						|
  e.history = {
 | 
						|
    undos: [],
 | 
						|
    redos: []
 | 
						|
  };
 | 
						|
 | 
						|
  e.redo = () => {
 | 
						|
    var {
 | 
						|
      history
 | 
						|
    } = e;
 | 
						|
    var {
 | 
						|
      redos
 | 
						|
    } = history;
 | 
						|
 | 
						|
    if (redos.length > 0) {
 | 
						|
      var batch = redos[redos.length - 1];
 | 
						|
      HistoryEditor.withoutSaving(e, () => {
 | 
						|
        Editor.withoutNormalizing(e, () => {
 | 
						|
          for (var op of batch) {
 | 
						|
            e.apply(op);
 | 
						|
          }
 | 
						|
        });
 | 
						|
      });
 | 
						|
      history.redos.pop();
 | 
						|
      history.undos.push(batch);
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  e.undo = () => {
 | 
						|
    var {
 | 
						|
      history
 | 
						|
    } = e;
 | 
						|
    var {
 | 
						|
      undos
 | 
						|
    } = history;
 | 
						|
 | 
						|
    if (undos.length > 0) {
 | 
						|
      var batch = undos[undos.length - 1];
 | 
						|
      HistoryEditor.withoutSaving(e, () => {
 | 
						|
        Editor.withoutNormalizing(e, () => {
 | 
						|
          var inverseOps = batch.map(Operation.inverse).reverse();
 | 
						|
 | 
						|
          for (var op of inverseOps) {
 | 
						|
            e.apply(op);
 | 
						|
          }
 | 
						|
        });
 | 
						|
      });
 | 
						|
      history.redos.push(batch);
 | 
						|
      history.undos.pop();
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  e.apply = op => {
 | 
						|
    var {
 | 
						|
      operations,
 | 
						|
      history
 | 
						|
    } = e;
 | 
						|
    var {
 | 
						|
      undos
 | 
						|
    } = history;
 | 
						|
    var lastBatch = undos[undos.length - 1];
 | 
						|
    var lastOp = lastBatch && lastBatch[lastBatch.length - 1];
 | 
						|
    var overwrite = shouldOverwrite(op, lastOp);
 | 
						|
    var save = HistoryEditor.isSaving(e);
 | 
						|
    var merge = HistoryEditor.isMerging(e);
 | 
						|
 | 
						|
    if (save == null) {
 | 
						|
      save = shouldSave(op);
 | 
						|
    }
 | 
						|
 | 
						|
    if (save) {
 | 
						|
      if (merge == null) {
 | 
						|
        if (lastBatch == null) {
 | 
						|
          merge = false;
 | 
						|
        } else if (operations.length !== 0) {
 | 
						|
          merge = true;
 | 
						|
        } else {
 | 
						|
          merge = shouldMerge(op, lastOp) || overwrite;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      if (lastBatch && merge) {
 | 
						|
        if (overwrite) {
 | 
						|
          lastBatch.pop();
 | 
						|
        }
 | 
						|
 | 
						|
        lastBatch.push(op);
 | 
						|
      } else {
 | 
						|
        var batch = [op];
 | 
						|
        undos.push(batch);
 | 
						|
      }
 | 
						|
 | 
						|
      while (undos.length > 100) {
 | 
						|
        undos.shift();
 | 
						|
      }
 | 
						|
 | 
						|
      if (shouldClear(op)) {
 | 
						|
        history.redos = [];
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    apply(op);
 | 
						|
  };
 | 
						|
 | 
						|
  return e;
 | 
						|
};
 | 
						|
/**
 | 
						|
 * Check whether to merge an operation into the previous operation.
 | 
						|
 */
 | 
						|
 | 
						|
var shouldMerge = (op, prev) => {
 | 
						|
  if (op.type === 'set_selection') {
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  if (prev && op.type === 'insert_text' && prev.type === 'insert_text' && op.offset === prev.offset + prev.text.length && Path.equals(op.path, prev.path)) {
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  if (prev && op.type === 'remove_text' && prev.type === 'remove_text' && op.offset + op.text.length === prev.offset && Path.equals(op.path, prev.path)) {
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  return false;
 | 
						|
};
 | 
						|
/**
 | 
						|
 * Check whether an operation needs to be saved to the history.
 | 
						|
 */
 | 
						|
 | 
						|
 | 
						|
var shouldSave = (op, prev) => {
 | 
						|
  if (op.type === 'set_selection' && (op.properties == null || op.newProperties == null)) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  return true;
 | 
						|
};
 | 
						|
/**
 | 
						|
 * Check whether an operation should overwrite the previous one.
 | 
						|
 */
 | 
						|
 | 
						|
 | 
						|
var shouldOverwrite = (op, prev) => {
 | 
						|
  if (prev && op.type === 'set_selection' && prev.type === 'set_selection') {
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  return false;
 | 
						|
};
 | 
						|
/**
 | 
						|
 * Check whether an operation should clear the redos stack.
 | 
						|
 */
 | 
						|
 | 
						|
 | 
						|
var shouldClear = op => {
 | 
						|
  if (op.type === 'set_selection') {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  return true;
 | 
						|
};
 | 
						|
 | 
						|
export { HISTORY, History, HistoryEditor, MERGING, SAVING, withHistory };
 | 
						|
//# sourceMappingURL=index.es.js.map
 |