1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-09-03 04:02:33 +02:00

Remove commands (#3351)

* remove commands in favor of editor-level functions

* update examples

* fix lint
This commit is contained in:
Ian Storm Taylor
2019-12-18 15:00:42 -05:00
committed by GitHub
parent c2d7905e19
commit 0bbe121d76
578 changed files with 3532 additions and 3370 deletions

View File

@@ -1,29 +0,0 @@
import { Command } from 'slate'
export interface RedoCommand {
type: 'redo'
}
export interface UndoCommand {
type: 'undo'
}
export type HistoryCommand = RedoCommand | UndoCommand
export const HistoryCommand = {
/**
* Check if a value is a `HistoryCommand` object.
*/
isHistoryCommand(value: any): value is HistoryCommand {
if (Command.isCommand(value)) {
switch (value.type) {
case 'redo':
case 'undo':
return true
}
}
return false
},
}

View File

@@ -15,6 +15,8 @@ export const MERGING = new WeakMap<Editor, boolean | undefined>()
export interface HistoryEditor extends Editor {
history: History
undo: () => void
redo: () => void
}
export const HistoryEditor = {
@@ -30,7 +32,7 @@ export const HistoryEditor = {
* Get the merge flag's current value.
*/
isMerging(editor: Editor): boolean | undefined {
isMerging(editor: HistoryEditor): boolean | undefined {
return MERGING.get(editor)
},
@@ -38,16 +40,32 @@ export const HistoryEditor = {
* Get the saving flag's current value.
*/
isSaving(editor: Editor): boolean | undefined {
isSaving(editor: HistoryEditor): boolean | undefined {
return SAVING.get(editor)
},
/**
* Redo to the previous saved state.
*/
redo(editor: HistoryEditor): void {
editor.redo()
},
/**
* Undo to the previous saved state.
*/
undo(editor: HistoryEditor): void {
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: Editor, fn: () => void): void {
withoutMerging(editor: HistoryEditor, fn: () => void): void {
const prev = HistoryEditor.isMerging(editor)
MERGING.set(editor, false)
fn()
@@ -59,7 +77,7 @@ export const HistoryEditor = {
* their operations into the history.
*/
withoutSaving(editor: Editor, fn: () => void): void {
withoutSaving(editor: HistoryEditor, fn: () => void): void {
const prev = HistoryEditor.isSaving(editor)
SAVING.set(editor, false)
fn()

View File

@@ -1,4 +1,3 @@
export * from './history'
export * from './history-command'
export * from './history-editor'
export * from './with-history'

View File

@@ -1,6 +1,5 @@
import { Editor, Command, Operation, Path } from 'slate'
import { Editor, Operation, Path } from 'slate'
import { HistoryCommand } from './history-command'
import { HistoryEditor } from './history-editor'
/**
@@ -9,114 +8,109 @@ import { HistoryEditor } from './history-editor'
*/
export const withHistory = (editor: Editor): HistoryEditor => {
const { apply, exec } = editor
editor.history = { undos: [], redos: [] }
const e = editor as HistoryEditor
const { apply } = e
e.history = { undos: [], redos: [] }
editor.exec = (command: Command) => {
if (
HistoryEditor.isHistoryEditor(editor) &&
HistoryCommand.isHistoryCommand(command)
) {
const { history } = editor
const { undos, redos } = history
e.redo = () => {
const { history } = e
const { redos } = history
if (command.type === 'redo' && redos.length > 0) {
const batch = redos[redos.length - 1]
if (redos.length > 0) {
const batch = redos[redos.length - 1]
HistoryEditor.withoutSaving(editor, () => {
Editor.withoutNormalizing(editor, () => {
for (const op of batch) {
editor.apply(op)
}
})
HistoryEditor.withoutSaving(e, () => {
Editor.withoutNormalizing(e, () => {
for (const op of batch) {
e.apply(op)
}
})
})
history.redos.pop()
history.undos.push(batch)
return
}
if (command.type === 'undo' && undos.length > 0) {
const batch = undos[undos.length - 1]
HistoryEditor.withoutSaving(editor, () => {
Editor.withoutNormalizing(editor, () => {
const inverseOps = batch.map(Operation.inverse).reverse()
for (const op of inverseOps) {
// If the final operation is deselecting the editor, skip it. This is
if (
op === inverseOps[inverseOps.length - 1] &&
op.type === 'set_selection' &&
op.newProperties == null
) {
continue
} else {
editor.apply(op)
}
}
})
})
history.redos.push(batch)
history.undos.pop()
return
}
history.redos.pop()
history.undos.push(batch)
}
exec(command)
}
editor.apply = (op: Operation) => {
if (HistoryEditor.isHistoryEditor(editor)) {
const { operations, history } = editor
const { undos } = history
const lastBatch = undos[undos.length - 1]
const lastOp = lastBatch && lastBatch[lastBatch.length - 1]
const overwrite = shouldOverwrite(op, lastOp)
let save = HistoryEditor.isSaving(editor)
let merge = HistoryEditor.isMerging(editor)
e.undo = () => {
const { history } = e
const { undos } = history
if (save == null) {
save = shouldSave(op, lastOp)
if (undos.length > 0) {
const batch = undos[undos.length - 1]
HistoryEditor.withoutSaving(e, () => {
Editor.withoutNormalizing(e, () => {
const inverseOps = batch.map(Operation.inverse).reverse()
for (const op of inverseOps) {
// If the final operation is deselecting the editor, skip it. This is
if (
op === inverseOps[inverseOps.length - 1] &&
op.type === 'set_selection' &&
op.newProperties == null
) {
continue
} else {
e.apply(op)
}
}
})
})
history.redos.push(batch)
history.undos.pop()
}
}
e.apply = (op: Operation) => {
const { operations, history } = e
const { undos } = history
const lastBatch = undos[undos.length - 1]
const lastOp = lastBatch && lastBatch[lastBatch.length - 1]
const overwrite = shouldOverwrite(op, lastOp)
let save = HistoryEditor.isSaving(e)
let merge = HistoryEditor.isMerging(e)
if (save == null) {
save = shouldSave(op, lastOp)
}
if (save) {
if (merge == null) {
if (lastBatch == null) {
merge = false
} else if (operations.length !== 0) {
merge = true
} else {
merge = shouldMerge(op, lastOp) || overwrite
}
}
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()
}
if (lastBatch && merge) {
if (overwrite) {
lastBatch.pop()
}
lastBatch.push(op)
} else {
const batch = [op]
undos.push(batch)
}
lastBatch.push(op)
} else {
const batch = [op]
undos.push(batch)
}
while (undos.length > 100) {
undos.shift()
}
while (undos.length > 100) {
undos.shift()
}
if (shouldClear(op)) {
history.redos = []
}
if (shouldClear(op)) {
history.redos = []
}
}
apply(op)
}
return editor as HistoryEditor
return e
}
/**

View File

@@ -8,7 +8,7 @@ describe('slate-history', () => {
const { input, run, output } = module
const editor = withTest(withHistory(input))
run(editor)
editor.exec({ type: 'undo' })
editor.undo()
assert.deepEqual(editor.children, output.children)
assert.deepEqual(editor.selection, output.selection)
})

View File

@@ -3,7 +3,7 @@
import { jsx } from '../..'
export const run = editor => {
editor.exec({ type: 'delete_backward' })
editor.deleteBackward()
}
export const input = (

View File

@@ -3,7 +3,7 @@
import { jsx } from '../..'
export const run = editor => {
editor.exec({ type: 'delete_backward' })
editor.deleteBackward()
}
export const input = (

View File

@@ -1,10 +1,10 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { Transforms } from 'slate'
import { jsx } from '../..'
export const run = editor => {
Editor.delete(editor)
Transforms.delete(editor)
}
export const input = (

View File

@@ -1,10 +1,10 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { Transforms } from 'slate'
import { jsx } from '../..'
export const run = editor => {
Editor.delete(editor)
Transforms.delete(editor)
}
export const input = (

View File

@@ -1,10 +1,10 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { Transforms } from 'slate'
import { jsx } from '../..'
export const run = editor => {
Editor.delete(editor)
Transforms.delete(editor)
}
export const input = (

View File

@@ -4,7 +4,7 @@ import { Editor } from 'slate'
import { jsx } from '../..'
export const run = editor => {
editor.exec({ type: 'insert_break' })
editor.insertBreak()
}
export const input = (

View File

@@ -22,7 +22,7 @@ const fragment = (
)
export const run = editor => {
editor.exec({ type: 'insert_fragment', fragment })
editor.insertFragment(fragment)
}
export const input = (
@@ -38,3 +38,5 @@ export const input = (
)
export const output = input
export const skip = true

View File

@@ -3,7 +3,7 @@
import { jsx } from '../..'
export const run = editor => {
editor.exec({ type: 'insert_text', text: 'text' })
editor.insertText('text')
}
export const input = (

View File

@@ -3,9 +3,9 @@
import { jsx } from '../..'
export const run = editor => {
editor.exec({ type: 'insert_text', text: 't' })
editor.exec({ type: 'insert_text', text: 'w' })
editor.exec({ type: 'insert_text', text: 'o' })
editor.insertText('t')
editor.insertText('w')
editor.insertText('o')
}
export const input = (

View File

@@ -1,14 +1,14 @@
/** @jsx jsx */
import { Editor } from 'slate'
import { Transforms } from 'slate'
import { jsx } from '../..'
export const run = editor => {
editor.exec({ type: 'insert_text', text: 't' })
Editor.move(editor, { reverse: true })
editor.exec({ type: 'insert_text', text: 'w' })
Editor.move(editor, { reverse: true })
editor.exec({ type: 'insert_text', text: 'o' })
editor.insertText('t')
Transforms.move(editor, { reverse: true })
editor.insertText('w')
Transforms.move(editor, { reverse: true })
editor.insertText('o')
}
export const input = (