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:
@@ -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
|
||||
},
|
||||
}
|
@@ -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()
|
||||
|
@@ -1,4 +1,3 @@
|
||||
export * from './history'
|
||||
export * from './history-command'
|
||||
export * from './history-editor'
|
||||
export * from './with-history'
|
||||
|
@@ -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
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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)
|
||||
})
|
||||
|
@@ -3,7 +3,7 @@
|
||||
import { jsx } from '../..'
|
||||
|
||||
export const run = editor => {
|
||||
editor.exec({ type: 'delete_backward' })
|
||||
editor.deleteBackward()
|
||||
}
|
||||
|
||||
export const input = (
|
||||
|
@@ -3,7 +3,7 @@
|
||||
import { jsx } from '../..'
|
||||
|
||||
export const run = editor => {
|
||||
editor.exec({ type: 'delete_backward' })
|
||||
editor.deleteBackward()
|
||||
}
|
||||
|
||||
export const input = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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
|
||||
|
@@ -3,7 +3,7 @@
|
||||
import { jsx } from '../..'
|
||||
|
||||
export const run = editor => {
|
||||
editor.exec({ type: 'insert_text', text: 'text' })
|
||||
editor.insertText('text')
|
||||
}
|
||||
|
||||
export const input = (
|
||||
|
@@ -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 = (
|
||||
|
@@ -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 = (
|
||||
|
Reference in New Issue
Block a user