2021-10-14 17:56:40 +08:00
|
|
|
import { EditorState, Transaction } from 'prosemirror-state'
|
2020-11-17 04:42:35 +08:00
|
|
|
import { Editor } from './Editor'
|
2021-12-06 19:00:09 +08:00
|
|
|
import { createChainableState } from './helpers/createChainableState'
|
2020-11-03 00:18:12 +08:00
|
|
|
import {
|
2020-11-16 22:56:44 +08:00
|
|
|
SingleCommands,
|
|
|
|
ChainedCommands,
|
2020-11-17 00:25:55 +08:00
|
|
|
CanCommands,
|
2021-06-05 03:56:29 +08:00
|
|
|
AnyCommands,
|
2021-01-28 16:50:17 +08:00
|
|
|
CommandProps,
|
2020-11-17 04:42:35 +08:00
|
|
|
} from './types'
|
2020-09-23 03:25:32 +08:00
|
|
|
|
2021-12-06 19:00:09 +08:00
|
|
|
export class CommandManager {
|
2020-09-23 03:25:32 +08:00
|
|
|
|
|
|
|
editor: Editor
|
2020-09-24 06:29:05 +08:00
|
|
|
|
2021-10-14 17:56:40 +08:00
|
|
|
rawCommands: AnyCommands
|
2020-09-23 03:25:32 +08:00
|
|
|
|
2021-10-14 17:56:40 +08:00
|
|
|
customState?: EditorState
|
|
|
|
|
|
|
|
constructor(props: {
|
|
|
|
editor: Editor,
|
|
|
|
state?: EditorState,
|
|
|
|
}) {
|
|
|
|
this.editor = props.editor
|
|
|
|
this.rawCommands = this.editor.extensionManager.commands
|
|
|
|
this.customState = props.state
|
|
|
|
}
|
|
|
|
|
|
|
|
get hasCustomState(): boolean {
|
|
|
|
return !!this.customState
|
|
|
|
}
|
|
|
|
|
|
|
|
get state(): EditorState {
|
|
|
|
return this.customState || this.editor.state
|
2020-09-23 14:59:21 +08:00
|
|
|
}
|
|
|
|
|
2021-10-14 17:56:40 +08:00
|
|
|
get commands(): SingleCommands {
|
|
|
|
const { rawCommands, editor, state } = this
|
|
|
|
const { view } = editor
|
2020-12-01 19:45:30 +08:00
|
|
|
const { tr } = state
|
|
|
|
const props = this.buildProps(tr)
|
2020-11-13 16:58:30 +08:00
|
|
|
|
|
|
|
return Object.fromEntries(Object
|
2021-10-14 17:56:40 +08:00
|
|
|
.entries(rawCommands)
|
2020-11-13 16:58:30 +08:00
|
|
|
.map(([name, command]) => {
|
2021-06-05 03:56:29 +08:00
|
|
|
const method = (...args: any[]) => {
|
2021-02-17 01:00:40 +08:00
|
|
|
const callback = command(...args)(props)
|
2020-11-13 16:58:30 +08:00
|
|
|
|
2021-10-14 17:56:40 +08:00
|
|
|
if (!tr.getMeta('preventDispatch') && !this.hasCustomState) {
|
2020-12-02 16:28:55 +08:00
|
|
|
view.dispatch(tr)
|
|
|
|
}
|
2020-11-13 16:58:30 +08:00
|
|
|
|
|
|
|
return callback
|
|
|
|
}
|
|
|
|
|
|
|
|
return [name, method]
|
2021-06-05 03:56:29 +08:00
|
|
|
})) as unknown as SingleCommands
|
2020-11-13 16:58:30 +08:00
|
|
|
}
|
|
|
|
|
2021-10-14 17:56:40 +08:00
|
|
|
get chain(): () => ChainedCommands {
|
|
|
|
return () => this.createChain()
|
|
|
|
}
|
|
|
|
|
|
|
|
get can(): () => CanCommands {
|
|
|
|
return () => this.createCan()
|
|
|
|
}
|
|
|
|
|
2021-01-28 16:50:17 +08:00
|
|
|
public createChain(startTr?: Transaction, shouldDispatch = true): ChainedCommands {
|
2021-10-14 17:56:40 +08:00
|
|
|
const { rawCommands, editor, state } = this
|
|
|
|
const { view } = editor
|
2020-09-23 03:25:32 +08:00
|
|
|
const callbacks: boolean[] = []
|
2020-09-23 05:06:37 +08:00
|
|
|
const hasStartTransaction = !!startTr
|
2020-11-13 16:58:30 +08:00
|
|
|
const tr = startTr || state.tr
|
2020-09-23 03:25:32 +08:00
|
|
|
|
2021-02-10 22:10:03 +08:00
|
|
|
const run = () => {
|
2021-10-14 17:56:40 +08:00
|
|
|
if (
|
|
|
|
!hasStartTransaction
|
|
|
|
&& shouldDispatch
|
|
|
|
&& !tr.getMeta('preventDispatch')
|
|
|
|
&& !this.hasCustomState
|
|
|
|
) {
|
2021-02-10 22:10:03 +08:00
|
|
|
view.dispatch(tr)
|
|
|
|
}
|
2020-09-23 03:25:32 +08:00
|
|
|
|
2021-05-03 09:04:10 +08:00
|
|
|
return callbacks.every(callback => callback === true)
|
2021-02-10 22:10:03 +08:00
|
|
|
}
|
2020-09-23 03:25:32 +08:00
|
|
|
|
2021-02-10 22:10:03 +08:00
|
|
|
const chain = {
|
2021-10-14 17:56:40 +08:00
|
|
|
...Object.fromEntries(Object.entries(rawCommands).map(([name, command]) => {
|
2021-04-27 05:33:45 +08:00
|
|
|
const chainedCommand = (...args: never[]) => {
|
2020-12-02 06:32:39 +08:00
|
|
|
const props = this.buildProps(tr, shouldDispatch)
|
2020-09-23 03:25:32 +08:00
|
|
|
const callback = command(...args)(props)
|
2020-12-02 06:32:39 +08:00
|
|
|
|
2020-09-23 03:25:32 +08:00
|
|
|
callbacks.push(callback)
|
|
|
|
|
2021-02-10 22:10:03 +08:00
|
|
|
return chain
|
2020-09-23 03:25:32 +08:00
|
|
|
}
|
2021-02-10 22:10:03 +08:00
|
|
|
|
|
|
|
return [name, chainedCommand]
|
|
|
|
})),
|
|
|
|
run,
|
|
|
|
} as unknown as ChainedCommands
|
|
|
|
|
|
|
|
return chain
|
2020-09-23 03:25:32 +08:00
|
|
|
}
|
|
|
|
|
2021-01-28 16:50:17 +08:00
|
|
|
public createCan(startTr?: Transaction): CanCommands {
|
2021-10-14 17:56:40 +08:00
|
|
|
const { rawCommands, state } = this
|
2021-02-16 18:27:58 +08:00
|
|
|
const dispatch = undefined
|
2020-11-13 16:58:30 +08:00
|
|
|
const tr = startTr || state.tr
|
2020-11-03 00:18:12 +08:00
|
|
|
const props = this.buildProps(tr, dispatch)
|
|
|
|
const formattedCommands = Object.fromEntries(Object
|
2021-10-14 17:56:40 +08:00
|
|
|
.entries(rawCommands)
|
2020-11-03 00:18:12 +08:00
|
|
|
.map(([name, command]) => {
|
2021-04-27 05:33:45 +08:00
|
|
|
return [name, (...args: never[]) => command(...args)({ ...props, dispatch })]
|
2021-06-05 03:56:29 +08:00
|
|
|
})) as unknown as SingleCommands
|
2020-11-03 00:18:12 +08:00
|
|
|
|
|
|
|
return {
|
|
|
|
...formattedCommands,
|
|
|
|
chain: () => this.createChain(tr, dispatch),
|
2020-11-17 00:25:55 +08:00
|
|
|
} as CanCommands
|
2020-11-03 00:18:12 +08:00
|
|
|
}
|
|
|
|
|
2021-01-28 16:50:17 +08:00
|
|
|
public buildProps(tr: Transaction, shouldDispatch = true): CommandProps {
|
2021-10-14 17:56:40 +08:00
|
|
|
const { rawCommands, editor, state } = this
|
|
|
|
const { view } = editor
|
2020-09-23 03:35:02 +08:00
|
|
|
|
2020-12-02 06:32:39 +08:00
|
|
|
if (state.storedMarks) {
|
|
|
|
tr.setStoredMarks(state.storedMarks)
|
|
|
|
}
|
|
|
|
|
2021-02-17 01:00:40 +08:00
|
|
|
const props: CommandProps = {
|
2020-09-23 05:06:37 +08:00
|
|
|
tr,
|
2020-09-23 03:35:02 +08:00
|
|
|
editor,
|
|
|
|
view,
|
2021-10-08 21:02:09 +08:00
|
|
|
state: createChainableState({
|
|
|
|
state,
|
|
|
|
transaction: tr,
|
|
|
|
}),
|
2020-11-02 21:29:58 +08:00
|
|
|
dispatch: shouldDispatch
|
2020-11-05 00:01:51 +08:00
|
|
|
? () => undefined
|
2020-11-02 21:29:58 +08:00
|
|
|
: undefined,
|
2020-09-23 05:06:37 +08:00
|
|
|
chain: () => this.createChain(tr),
|
2020-11-03 00:18:12 +08:00
|
|
|
can: () => this.createCan(tr),
|
2020-09-23 03:35:02 +08:00
|
|
|
get commands() {
|
|
|
|
return Object.fromEntries(Object
|
2021-10-14 17:56:40 +08:00
|
|
|
.entries(rawCommands)
|
2020-09-23 03:35:02 +08:00
|
|
|
.map(([name, command]) => {
|
2021-04-27 05:33:45 +08:00
|
|
|
return [name, (...args: never[]) => command(...args)(props)]
|
2021-06-05 03:56:29 +08:00
|
|
|
})) as unknown as SingleCommands
|
2020-09-24 06:29:05 +08:00
|
|
|
},
|
2020-09-23 03:35:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return props
|
|
|
|
}
|
|
|
|
|
2020-09-24 06:29:05 +08:00
|
|
|
}
|