add Commands interface

This commit is contained in:
Philipp Kühn
2021-02-10 09:59:35 +01:00
parent 0ed368e9f4
commit 290ff76e37
100 changed files with 695 additions and 487 deletions

View File

@@ -16,6 +16,7 @@ import {
EditorOptions,
EditorContent,
CommandSpec,
Commands,
CanCommands,
ChainedCommands,
SingleCommands,

View File

@@ -2,9 +2,9 @@ import { Plugin, Transaction } from 'prosemirror-state'
import { InputRule } from 'prosemirror-inputrules'
import { Editor } from './Editor'
import mergeDeep from './utilities/mergeDeep'
import { GlobalAttributes } from './types'
import { GlobalAttributes, Commands } from './types'
export interface ExtensionConfig<Options = any, Commands = {}> {
export interface ExtensionConfig<Options = any> {
/**
* Name
*/
@@ -28,7 +28,7 @@ export interface ExtensionConfig<Options = any, Commands = {}> {
addCommands?: (this: {
options: Options,
editor: Editor,
}) => Commands,
}) => Partial<Commands>,
/**
* Keyboard shortcuts
@@ -136,7 +136,7 @@ export interface ExtensionConfig<Options = any, Commands = {}> {
}) => void) | null,
}
export class Extension<Options = any, Commands = any> {
export class Extension<Options = any> {
type = 'extension'
config: Required<ExtensionConfig> = {
@@ -159,7 +159,7 @@ export class Extension<Options = any, Commands = any> {
options!: Options
constructor(config: ExtensionConfig<Options, Commands>) {
constructor(config: ExtensionConfig<Options>) {
this.config = {
...this.config,
...config,
@@ -168,13 +168,13 @@ export class Extension<Options = any, Commands = any> {
this.options = this.config.defaultOptions
}
static create<O, C>(config: ExtensionConfig<O, C>) {
return new Extension<O, C>(config)
static create<O>(config: ExtensionConfig<O>) {
return new Extension<O>(config)
}
configure(options: Partial<Options> = {}) {
return Extension
.create<Options, Commands>(this.config as ExtensionConfig<Options, Commands>)
.create<Options>(this.config as ExtensionConfig<Options>)
.#configure(options)
}
@@ -184,10 +184,10 @@ export class Extension<Options = any, Commands = any> {
return this
}
extend<ExtendedOptions = Options, ExtendedCommands = Commands>(extendedConfig: Partial<ExtensionConfig<ExtendedOptions, ExtendedCommands>>) {
return new Extension<ExtendedOptions, ExtendedCommands>({
extend<ExtendedOptions = Options>(extendedConfig: Partial<ExtensionConfig<ExtendedOptions>>) {
return new Extension<ExtendedOptions>({
...this.config,
...extendedConfig,
} as ExtensionConfig<ExtendedOptions, ExtendedCommands>)
} as ExtensionConfig<ExtendedOptions>)
}
}

View File

@@ -34,6 +34,7 @@ export default class ExtensionManager {
const commands = extension.config.addCommands.bind(context)()
// @ts-ignore
editor.registerCommands(commands)
if (typeof extension.config.onCreate === 'function') {

View File

@@ -8,10 +8,10 @@ import { Plugin, Transaction } from 'prosemirror-state'
import { InputRule } from 'prosemirror-inputrules'
import { ExtensionConfig } from './Extension'
import mergeDeep from './utilities/mergeDeep'
import { Attributes, Overwrite } from './types'
import { Attributes, Overwrite, Commands } from './types'
import { Editor } from './Editor'
export interface MarkConfig<Options = any, Commands = {}> extends Overwrite<ExtensionConfig<Options, Commands>, {
export interface MarkConfig<Options = any> extends Overwrite<ExtensionConfig<Options>, {
/**
* Inclusive
*/
@@ -70,7 +70,7 @@ export interface MarkConfig<Options = any, Commands = {}> extends Overwrite<Exte
options: Options,
editor: Editor,
type: MarkType,
}) => Commands,
}) => Partial<Commands>,
/**
* Keyboard shortcuts
@@ -189,7 +189,7 @@ export interface MarkConfig<Options = any, Commands = {}> extends Overwrite<Exte
}) => void) | null,
}> {}
export class Mark<Options = any, Commands = {}> {
export class Mark<Options = any> {
type = 'mark'
config: Required<MarkConfig> = {
@@ -219,7 +219,7 @@ export class Mark<Options = any, Commands = {}> {
options!: Options
constructor(config: MarkConfig<Options, Commands>) {
constructor(config: MarkConfig<Options>) {
this.config = {
...this.config,
...config,
@@ -228,13 +228,13 @@ export class Mark<Options = any, Commands = {}> {
this.options = this.config.defaultOptions
}
static create<O, C>(config: MarkConfig<O, C>) {
return new Mark<O, C>(config)
static create<O>(config: MarkConfig<O>) {
return new Mark<O>(config)
}
configure(options: Partial<Options> = {}) {
return Mark
.create<Options, Commands>(this.config as MarkConfig<Options, Commands>)
.create<Options>(this.config as MarkConfig<Options>)
.#configure(options)
}
@@ -244,10 +244,10 @@ export class Mark<Options = any, Commands = {}> {
return this
}
extend<ExtendedOptions = Options, ExtendedCommands = Commands>(extendedConfig: Partial<MarkConfig<ExtendedOptions, ExtendedCommands>>) {
return new Mark<ExtendedOptions, ExtendedCommands>({
extend<ExtendedOptions = Options>(extendedConfig: Partial<MarkConfig<ExtendedOptions>>) {
return new Mark<ExtendedOptions>({
...this.config,
...extendedConfig,
} as MarkConfig<ExtendedOptions, ExtendedCommands>)
} as MarkConfig<ExtendedOptions>)
}
}

View File

@@ -9,10 +9,12 @@ import { Plugin, Transaction } from 'prosemirror-state'
import { InputRule } from 'prosemirror-inputrules'
import { ExtensionConfig } from './Extension'
import mergeDeep from './utilities/mergeDeep'
import { Attributes, NodeViewRenderer, Overwrite } from './types'
import {
Attributes, NodeViewRenderer, Overwrite, Commands,
} from './types'
import { Editor } from './Editor'
export interface NodeConfig<Options = any, Commands = {}> extends Overwrite<ExtensionConfig<Options, Commands>, {
export interface NodeConfig<Options = any> extends Overwrite<ExtensionConfig<Options>, {
/**
* TopNode
*/
@@ -125,7 +127,7 @@ export interface NodeConfig<Options = any, Commands = {}> extends Overwrite<Exte
options: Options,
editor: Editor,
type: NodeType,
}) => Commands,
}) => Partial<Commands>,
/**
* Keyboard shortcuts
@@ -135,7 +137,8 @@ export interface NodeConfig<Options = any, Commands = {}> extends Overwrite<Exte
editor: Editor,
type: NodeType,
}) => {
[key: string]: any
// [key: string]: any
[key: string]: () => boolean
},
/**
@@ -253,7 +256,7 @@ export interface NodeConfig<Options = any, Commands = {}> extends Overwrite<Exte
}) => void) | null,
}> {}
export class Node<Options = any, Commands = {}> {
export class Node<Options = any> {
type = 'node'
config: Required<NodeConfig> = {
@@ -292,7 +295,7 @@ export class Node<Options = any, Commands = {}> {
options!: Options
constructor(config: NodeConfig<Options, Commands>) {
constructor(config: NodeConfig<Options>) {
this.config = {
...this.config,
...config,
@@ -301,13 +304,13 @@ export class Node<Options = any, Commands = {}> {
this.options = this.config.defaultOptions
}
static create<O, C>(config: NodeConfig<O, C>) {
return new Node<O, C>(config)
static create<O>(config: NodeConfig<O>) {
return new Node<O>(config)
}
configure(options: Partial<Options> = {}) {
return Node
.create<Options, Commands>(this.config as NodeConfig<Options, Commands>)
.create<Options>(this.config as NodeConfig<Options>)
.#configure(options)
}
@@ -317,10 +320,10 @@ export class Node<Options = any, Commands = {}> {
return this
}
extend<ExtendedOptions = Options, ExtendedCommands = Commands>(extendedConfig: Partial<NodeConfig<ExtendedOptions, ExtendedCommands>>) {
return new Node<ExtendedOptions, ExtendedCommands>({
extend<ExtendedOptions = Options>(extendedConfig: Partial<NodeConfig<ExtendedOptions>>) {
return new Node<ExtendedOptions>({
...this.config,
...extendedConfig,
} as NodeConfig<ExtendedOptions, ExtendedCommands>)
} as NodeConfig<ExtendedOptions>)
}
}

View File

@@ -1,12 +1,18 @@
import { Command } from '../types'
import { Command, Commands } from '../types'
/**
* Removes focus from the editor.
*/
export const blur = (): Command => ({ view }) => {
export const blur: Commands['blur'] = () => ({ view }) => {
const element = view.dom as HTMLElement
element.blur()
return true
}
declare module '@tiptap/core' {
interface Commands {
blur: () => Command,
}
}

View File

@@ -1,8 +1,14 @@
import { Command } from '../types'
import { Command, Commands } from '../types'
/**
* Clear the whole document.
*/
export const clearContent = (emitUpdate: Boolean = false): Command => ({ commands }) => {
export const clearContent: Commands['clearContent'] = (emitUpdate = false) => ({ commands }) => {
return commands.setContent('', emitUpdate)
}
declare module '@tiptap/core' {
interface Commands {
clearContent: (emitUpdate: Boolean) => Command,
}
}

View File

@@ -1,10 +1,10 @@
import { liftTarget } from 'prosemirror-transform'
import { Command } from '../types'
import { Command, Commands } from '../types'
/**
* Normalize nodes to a simple paragraph.
*/
export const clearNodes = (): Command => ({ state, tr, dispatch }) => {
export const clearNodes: Commands['clearNodes'] = () => ({ state, tr, dispatch }) => {
const { selection } = tr
const { from, to } = selection
@@ -30,3 +30,9 @@ export const clearNodes = (): Command => ({ state, tr, dispatch }) => {
return true
}
declare module '@tiptap/core' {
interface Commands {
clearNodes: () => Command,
}
}

View File

@@ -1,8 +1,14 @@
import { Command } from '../types'
import { Command, Commands } from '../types'
/**
* Define a command inline.
*/
export const command = (fn: (props: Parameters<Command>[0]) => boolean): Command => props => {
export const command: Commands['command'] = fn => props => {
return fn(props)
}
declare module '@tiptap/core' {
interface Commands {
command: (fn: (props: Parameters<Command>[0]) => boolean) => Command,
}
}

View File

@@ -1,9 +1,15 @@
import { createParagraphNear as originalCreateParagraphNear } from 'prosemirror-commands'
import { Command } from '../types'
import { Command, Commands } from '../types'
/**
* Create a paragraph nearby.
*/
export const createParagraphNear = (): Command => ({ state, dispatch }) => {
export const createParagraphNear: Commands['createParagraphNear'] = () => ({ state, dispatch }) => {
return originalCreateParagraphNear(state, dispatch)
}
declare module '@tiptap/core' {
interface Commands {
createParagraphNear: () => Command,
}
}

View File

@@ -1,9 +1,9 @@
import { Command, Range } from '../types'
import { Command, Commands, Range } from '../types'
/**
* Delete a given range.
*/
export const deleteRange = (range: Range): Command => ({ tr, dispatch }) => {
export const deleteRange: Commands['deleteRange'] = range => ({ tr, dispatch }) => {
const { from, to } = range
if (dispatch) {
@@ -12,3 +12,9 @@ export const deleteRange = (range: Range): Command => ({ tr, dispatch }) => {
return true
}
declare module '@tiptap/core' {
interface Commands {
deleteRange: (range: Range) => Command,
}
}

View File

@@ -1,9 +1,15 @@
import { deleteSelection as originalDeleteSelection } from 'prosemirror-commands'
import { Command } from '../types'
import { Command, Commands } from '../types'
/**
* Delete the selection, if there is one.
*/
export const deleteSelection = (): Command => ({ state, dispatch }) => {
export const deleteSelection: Commands['deleteSelection'] = () => ({ state, dispatch }) => {
return originalDeleteSelection(state, dispatch)
}
declare module '@tiptap/core' {
interface Commands {
deleteSelection: () => Command,
}
}

View File

@@ -1,8 +1,14 @@
import { Command } from '../types'
import { Command, Commands } from '../types'
/**
* Trigger enter.
*/
export const enter = (): Command => ({ commands }) => {
export const enter: Commands['enter'] = () => ({ commands }) => {
return commands.keyboardShortcut('Enter')
}
declare module '@tiptap/core' {
interface Commands {
enter: () => Command,
}
}

View File

@@ -1,9 +1,15 @@
import { exitCode as originalExitCode } from 'prosemirror-commands'
import { Command } from '../types'
import { Command, Commands } from '../types'
/**
* Exit from a code block.
*/
export const exitCode = (): Command => ({ state, dispatch }) => {
export const exitCode: Commands['exitCode'] = () => ({ state, dispatch }) => {
return originalExitCode(state, dispatch)
}
declare module '@tiptap/core' {
interface Commands {
exitCode: () => Command,
}
}

View File

@@ -1,13 +1,13 @@
import { TextSelection } from 'prosemirror-state'
import { MarkType } from 'prosemirror-model'
import { Command } from '../types'
import { Command, Commands } from '../types'
import getMarkType from '../helpers/getMarkType'
import getMarkRange from '../helpers/getMarkRange'
/**
* Extends the text selection to the current mark.
*/
export const extendMarkRange = (typeOrName: string | MarkType): Command => ({ tr, state, dispatch }) => {
export const extendMarkRange: Commands['extendMarkRange'] = typeOrName => ({ tr, state, dispatch }) => {
const type = getMarkType(typeOrName, state.schema)
const { doc, selection } = tr
const { $from, empty } = selection
@@ -24,3 +24,9 @@ export const extendMarkRange = (typeOrName: string | MarkType): Command => ({ tr
return true
}
declare module '@tiptap/core' {
interface Commands {
extendMarkRange: (typeOrName: string | MarkType) => Command,
}
}

View File

@@ -1,9 +1,9 @@
import { Command } from '../types'
import { Command, Commands } from '../types'
/**
* Runs one command after the other and stops at the first which returns true.
*/
export const first = (commands: Command[] | ((props: Parameters<Command>[0]) => Command[])): Command => props => {
export const first: Commands['first'] = commands => props => {
const items = typeof commands === 'function'
? commands(props)
: commands
@@ -16,3 +16,9 @@ export const first = (commands: Command[] | ((props: Parameters<Command>[0]) =>
return false
}
declare module '@tiptap/core' {
interface Commands {
first: (commands: Command[] | ((props: Parameters<Command>[0]) => Command[])) => Command,
}
}

View File

@@ -1,5 +1,5 @@
import { EditorState, TextSelection } from 'prosemirror-state'
import { Command, FocusPosition } from '../types'
import { Command, Commands, FocusPosition } from '../types'
import minMax from '../utilities/minMax'
import isTextSelection from '../helpers/isTextSelection'
@@ -33,7 +33,7 @@ function resolveSelection(state: EditorState, position: FocusPosition = null) {
/**
* Focus the editor at the given position.
*/
export const focus = (position: FocusPosition = null): Command => ({
export const focus: Commands['focus'] = (position = null) => ({
editor,
view,
tr,
@@ -62,3 +62,9 @@ export const focus = (position: FocusPosition = null): Command => ({
return true
}
declare module '@tiptap/core' {
interface Commands {
focus: (position?: FocusPosition) => Command,
}
}

View File

@@ -2,7 +2,7 @@ import { DOMParser } from 'prosemirror-model'
import { Selection, Transaction } from 'prosemirror-state'
import { ReplaceStep, ReplaceAroundStep } from 'prosemirror-transform'
import elementFromString from '../utilities/elementFromString'
import { Command } from '../types'
import { Command, Commands } from '../types'
// TODO: move to utils
// https://github.com/ProseMirror/prosemirror-state/blob/master/src/selection.js#L466
@@ -20,7 +20,7 @@ function selectionToInsertionEnd(tr: Transaction, startLen: number, bias: number
/**
* Insert a string of HTML at the current position.
*/
export const insertHTML = (value: string): Command => ({ tr, state, dispatch }) => {
export const insertHTML: Commands['insertHTML'] = value => ({ tr, state, dispatch }) => {
const { selection } = tr
const element = elementFromString(value)
const slice = DOMParser.fromSchema(state.schema).parseSlice(element)
@@ -32,3 +32,9 @@ export const insertHTML = (value: string): Command => ({ tr, state, dispatch })
return true
}
declare module '@tiptap/core' {
interface Commands {
insertHTML: (value: string) => Command,
}
}

View File

@@ -1,12 +1,18 @@
import { Command } from '../types'
import { Command, Commands } from '../types'
/**
* Insert a string of text at the current position.
*/
export const insertText = (value: string): Command => ({ tr, dispatch }) => {
export const insertText: Commands['insertText'] = value => ({ tr, dispatch }) => {
if (dispatch) {
tr.insertText(value)
}
return true
}
declare module '@tiptap/core' {
interface Commands {
insertText: (value: string) => Command,
}
}

View File

@@ -1,9 +1,15 @@
import { joinBackward as originalJoinBackward } from 'prosemirror-commands'
import { Command } from '../types'
import { Command, Commands } from '../types'
/**
* Join two nodes backward.
*/
export const joinBackward = (): Command => ({ state, dispatch }) => {
export const joinBackward: Commands['joinBackward'] = () => ({ state, dispatch }) => {
return originalJoinBackward(state, dispatch)
}
declare module '@tiptap/core' {
interface Commands {
joinBackward: () => Command,
}
}

View File

@@ -1,9 +1,15 @@
import { joinForward as originalJoinForward } from 'prosemirror-commands'
import { Command } from '../types'
import { Command, Commands } from '../types'
/**
* Join two nodes forward.
*/
export const joinForward = (): Command => ({ state, dispatch }) => {
export const joinForward: Commands['joinForward'] = () => ({ state, dispatch }) => {
return originalJoinForward(state, dispatch)
}
declare module '@tiptap/core' {
interface Commands {
joinForward: () => Command,
}
}

View File

@@ -1,4 +1,4 @@
import { Command } from '../types'
import { Command, Commands } from '../types'
const mac = typeof navigator !== 'undefined' ? /Mac/.test(navigator.platform) : false
@@ -59,7 +59,7 @@ function normalizeKeyName(name: string) {
/**
* Trigger a keyboard shortcut.
*/
export const keyboardShortcut = (name: string): Command => ({
export const keyboardShortcut: Commands['keyboardShortcut'] = name => ({
editor,
view,
tr,
@@ -93,3 +93,9 @@ export const keyboardShortcut = (name: string): Command => ({
return true
}
declare module '@tiptap/core' {
interface Commands {
keyboardShortcut: (name: string) => Command,
}
}

View File

@@ -1,13 +1,13 @@
import { lift as originalLift } from 'prosemirror-commands'
import { NodeType } from 'prosemirror-model'
import { Command } from '../types'
import { Command, Commands, AnyObject } from '../types'
import isNodeActive from '../helpers/isNodeActive'
import getNodeType from '../helpers/getNodeType'
/**
* Removes an existing wrap.
*/
export const lift = (typeOrName: string | NodeType, attributes = {}): Command => ({ state, dispatch }) => {
export const lift: Commands['lift'] = (typeOrName, attributes = {}) => ({ state, dispatch }) => {
const type = getNodeType(typeOrName, state.schema)
const isActive = isNodeActive(state, type, attributes)
@@ -17,3 +17,9 @@ export const lift = (typeOrName: string | NodeType, attributes = {}): Command =>
return originalLift(state, dispatch)
}
declare module '@tiptap/core' {
interface Commands {
lift: (typeOrName: string | NodeType, attributes?: AnyObject) => Command,
}
}

View File

@@ -1,9 +1,15 @@
import { liftEmptyBlock as originalLiftEmptyBlock } from 'prosemirror-commands'
import { Command } from '../types'
import { Command, Commands } from '../types'
/**
* Lift block if empty.
*/
export const liftEmptyBlock = (): Command => ({ state, dispatch }) => {
export const liftEmptyBlock: Commands['liftEmptyBlock'] = () => ({ state, dispatch }) => {
return originalLiftEmptyBlock(state, dispatch)
}
declare module '@tiptap/core' {
interface Commands {
liftEmptyBlock: () => Command,
}
}

View File

@@ -1,13 +1,19 @@
import { liftListItem as originalLiftListItem } from 'prosemirror-schema-list'
import { NodeType } from 'prosemirror-model'
import { Command } from '../types'
import { Command, Commands } from '../types'
import getNodeType from '../helpers/getNodeType'
/**
* Lift the list item into a wrapping list.
*/
export const liftListItem = (typeOrName: string | NodeType): Command => ({ state, dispatch }) => {
export const liftListItem: Commands['liftListItem'] = typeOrName => ({ state, dispatch }) => {
const type = getNodeType(typeOrName, state.schema)
return originalLiftListItem(type)(state, dispatch)
}
declare module '@tiptap/core' {
interface Commands {
liftListItem: (typeOrName: string | NodeType) => Command,
}
}

View File

@@ -1,9 +1,15 @@
import { newlineInCode as originalNewlineInCode } from 'prosemirror-commands'
import { Command } from '../types'
import { Command, Commands } from '../types'
/**
* Add a newline character in code.
*/
export const newlineInCode = (): Command => ({ state, dispatch }) => {
export const newlineInCode: Commands['newlineInCode'] = () => ({ state, dispatch }) => {
return originalNewlineInCode(state, dispatch)
}
declare module '@tiptap/core' {
interface Commands {
newlineInCode: () => Command,
}
}

View File

@@ -1,12 +1,18 @@
import { NodeType } from 'prosemirror-model'
import { Command, AnyObject } from '../types'
import { Command, Commands, AnyObject } from '../types'
/**
* Replaces text with a node.
*/
export const replace = (typeOrName: string | NodeType, attributes: AnyObject = {}): Command => ({ state, commands }) => {
export const replace: Commands['replace'] = (typeOrName, attributes = {}) => ({ state, commands }) => {
const { from, to } = state.selection
const range = { from, to }
return commands.replaceRange(range, typeOrName, attributes)
}
declare module '@tiptap/core' {
interface Commands {
replace: (typeOrName: string | NodeType, attributes?: AnyObject) => Command,
}
}

View File

@@ -1,11 +1,16 @@
import { NodeType } from 'prosemirror-model'
import getNodeType from '../helpers/getNodeType'
import { Command, Range, AnyObject } from '../types'
import {
Command,
Commands,
Range,
AnyObject,
} from '../types'
/**
* Replaces text with a node within a range.
*/
export const replaceRange = (range: Range, typeOrName: string | NodeType, attributes: AnyObject = {}): Command => ({ tr, state, dispatch }) => {
export const replaceRange: Commands['replaceRange'] = (range, typeOrName, attributes = {}) => ({ tr, state, dispatch }) => {
const type = getNodeType(typeOrName, state.schema)
const { from, to } = range
const $from = tr.doc.resolve(from)
@@ -21,3 +26,9 @@ export const replaceRange = (range: Range, typeOrName: string | NodeType, attrib
return true
}
declare module '@tiptap/core' {
interface Commands {
replaceRange: (range: Range, typeOrName: string | NodeType, attributes?: AnyObject) => Command,
}
}

View File

@@ -1,12 +1,12 @@
import { NodeType } from 'prosemirror-model'
import getNodeType from '../helpers/getNodeType'
import deleteProps from '../utilities/deleteProps'
import { Command } from '../types'
import { Command, Commands } from '../types'
/**
* Resets node attributes to the default value.
*/
export const resetNodeAttributes = (typeOrName: string | NodeType, attributes: string | string[]): Command => ({ tr, state, dispatch }) => {
export const resetNodeAttributes: Commands['resetNodeAttributes'] = (typeOrName, attributes) => ({ tr, state, dispatch }) => {
const type = getNodeType(typeOrName, state.schema)
const { selection } = tr
const { from, to } = selection
@@ -19,3 +19,9 @@ export const resetNodeAttributes = (typeOrName: string | NodeType, attributes: s
return true
}
declare module '@tiptap/core' {
interface Commands {
resetNodeAttributes: (typeOrName: string | NodeType, attributes: string | string[]) => Command,
}
}

View File

@@ -1,12 +1,18 @@
import { Command } from '../types'
import { Command, Commands } from '../types'
/**
* Scroll the selection into view.
*/
export const scrollIntoView = (): Command => ({ tr, dispatch }) => {
export const scrollIntoView: Commands['scrollIntoView'] = () => ({ tr, dispatch }) => {
if (dispatch) {
tr.scrollIntoView()
}
return true
}
declare module '@tiptap/core' {
interface Commands {
scrollIntoView: () => Command,
}
}

View File

@@ -1,9 +1,15 @@
import { selectAll as originalSelectAll } from 'prosemirror-commands'
import { Command } from '../types'
import { Command, Commands } from '../types'
/**
* Select the whole document.
*/
export const selectAll = (): Command => ({ state, dispatch }) => {
export const selectAll: Commands['selectAll'] = () => ({ state, dispatch }) => {
return originalSelectAll(state, dispatch)
}
declare module '@tiptap/core' {
interface Commands {
selectAll: () => Command,
}
}

View File

@@ -1,9 +1,15 @@
import { selectNodeBackward as originalSelectNodeBackward } from 'prosemirror-commands'
import { Command } from '../types'
import { Command, Commands } from '../types'
/**
* Select a node backward.
*/
export const selectNodeBackward = (): Command => ({ state, dispatch }) => {
export const selectNodeBackward: Commands['selectNodeBackward'] = () => ({ state, dispatch }) => {
return originalSelectNodeBackward(state, dispatch)
}
declare module '@tiptap/core' {
interface Commands {
selectNodeBackward: () => Command,
}
}

View File

@@ -1,9 +1,15 @@
import { selectNodeForward as originalSelectNodeForward } from 'prosemirror-commands'
import { Command } from '../types'
import { Command, Commands } from '../types'
/**
* Select a node forward.
*/
export const selectNodeForward = (): Command => ({ state, dispatch }) => {
export const selectNodeForward: Commands['selectNodeForward'] = () => ({ state, dispatch }) => {
return originalSelectNodeForward(state, dispatch)
}
declare module '@tiptap/core' {
interface Commands {
selectNodeForward: () => Command,
}
}

View File

@@ -1,9 +1,15 @@
import { selectParentNode as originalSelectParentNode } from 'prosemirror-commands'
import { Command } from '../types'
import { Command, Commands } from '../types'
/**
* Select the parent node.
*/
export const selectParentNode = (): Command => ({ state, dispatch }) => {
export const selectParentNode: Commands['selectParentNode'] = () => ({ state, dispatch }) => {
return originalSelectParentNode(state, dispatch)
}
declare module '@tiptap/core' {
interface Commands {
selectParentNode: () => Command,
}
}

View File

@@ -1,10 +1,10 @@
import { TextSelection } from 'prosemirror-state'
import { Command } from '../types'
import { AnyObject, Command, Commands } from '../types'
/**
* Replace the whole document with new content.
*/
export const setContent = (content: string, emitUpdate: Boolean = false, parseOptions = {}): Command => ({ tr, editor, dispatch }) => {
export const setContent: Commands['setContent'] = (content, emitUpdate = false, parseOptions = {}) => ({ tr, editor, dispatch }) => {
const { createDocument } = editor
const { doc } = tr
const document = createDocument(content, parseOptions)
@@ -18,3 +18,9 @@ export const setContent = (content: string, emitUpdate: Boolean = false, parseOp
return true
}
declare module '@tiptap/core' {
interface Commands {
setContent: (content: string, emitUpdate?: Boolean, parseOptions?: AnyObject) => Command,
}
}

View File

@@ -1,12 +1,12 @@
import { MarkType } from 'prosemirror-model'
import { Command } from '../types'
import { AnyObject, Command, Commands } from '../types'
import getMarkType from '../helpers/getMarkType'
import getMarkAttributes from '../helpers/getMarkAttributes'
/**
* Add a mark with new attributes.
*/
export const setMark = (typeOrName: string | MarkType, attributes?: {}): Command => ({ tr, state, dispatch }) => {
export const setMark: Commands['setMark'] = (typeOrName, attributes = {}) => ({ tr, state, dispatch }) => {
const { selection } = tr
const { from, to, empty } = selection
const type = getMarkType(typeOrName, state.schema)
@@ -26,3 +26,9 @@ export const setMark = (typeOrName: string | MarkType, attributes?: {}): Command
return true
}
declare module '@tiptap/core' {
interface Commands {
setMark: (typeOrName: string | MarkType, attributes?: AnyObject) => Command,
}
}

View File

@@ -1,13 +1,19 @@
import { NodeType } from 'prosemirror-model'
import { setBlockType } from 'prosemirror-commands'
import { Command } from '../types'
import { AnyObject, Command, Commands } from '../types'
import getNodeType from '../helpers/getNodeType'
/**
* Replace a given range with a node.
*/
export const setNode = (typeOrName: string | NodeType, attrs = {}): Command => ({ state, dispatch }) => {
export const setNode: Commands['setNode'] = (typeOrName, attributes = {}) => ({ state, dispatch }) => {
const type = getNodeType(typeOrName, state.schema)
return setBlockType(type, attrs)(state, dispatch)
return setBlockType(type, attributes)(state, dispatch)
}
declare module '@tiptap/core' {
interface Commands {
setNode: (typeOrName: string | NodeType, attributes?: AnyObject) => Command,
}
}

View File

@@ -1,13 +1,19 @@
import { sinkListItem as originalSinkListItem } from 'prosemirror-schema-list'
import { NodeType } from 'prosemirror-model'
import { Command } from '../types'
import { Command, Commands } from '../types'
import getNodeType from '../helpers/getNodeType'
/**
* Sink the list item down into an inner list.
*/
export const sinkListItem = (typeOrName: string | NodeType): Command => ({ state, dispatch }) => {
export const sinkListItem: Commands['sinkListItem'] = typeOrName => ({ state, dispatch }) => {
const type = getNodeType(typeOrName, state.schema)
return originalSinkListItem(type)(state, dispatch)
}
declare module '@tiptap/core' {
interface Commands {
sinkListItem: (typeOrName: string | NodeType) => Command,
}
}

View File

@@ -1,7 +1,7 @@
import { canSplit } from 'prosemirror-transform'
import { ContentMatch, Fragment } from 'prosemirror-model'
import { EditorState, NodeSelection, TextSelection } from 'prosemirror-state'
import { Command } from '../types'
import { Command, Commands } from '../types'
import getSplittedAttributes from '../helpers/getSplittedAttributes'
function defaultBlockAt(match: ContentMatch) {
@@ -31,7 +31,7 @@ function keepMarks(state: EditorState) {
/**
* Forks a new node from an existing node.
*/
export const splitBlock = (options: Partial<SplitBlockOptions> = {}): Command => ({
export const splitBlock: Commands['splitBlock'] = (options = {}) => ({
tr,
state,
dispatch,
@@ -126,3 +126,9 @@ export const splitBlock = (options: Partial<SplitBlockOptions> = {}): Command =>
return true
}
declare module '@tiptap/core' {
interface Commands {
splitBlock: (options?: Partial<SplitBlockOptions>) => Command,
}
}

View File

@@ -6,14 +6,14 @@ import {
} from 'prosemirror-model'
import { canSplit } from 'prosemirror-transform'
import { TextSelection } from 'prosemirror-state'
import { Command } from '../types'
import { Command, Commands } from '../types'
import getNodeType from '../helpers/getNodeType'
import getSplittedAttributes from '../helpers/getSplittedAttributes'
/**
* Splits one list item into two list items.
*/
export const splitListItem = (typeOrName: string | NodeType): Command => ({
export const splitListItem: Commands['splitListItem'] = typeOrName => ({
tr, state, dispatch, editor,
}) => {
const type = getNodeType(typeOrName, state.schema)
@@ -110,3 +110,9 @@ export const splitListItem = (typeOrName: string | NodeType): Command => ({
return true
}
declare module '@tiptap/core' {
interface Commands {
splitListItem: (typeOrName: string | NodeType) => Command,
}
}

View File

@@ -1,5 +1,5 @@
import { NodeType } from 'prosemirror-model'
import { Command } from '../types'
import { Command, Commands } from '../types'
import getNodeType from '../helpers/getNodeType'
import findParentNode from '../helpers/findParentNode'
import isList from '../helpers/isList'
@@ -7,7 +7,7 @@ import isList from '../helpers/isList'
/**
* Toggle between different list types.
*/
export const toggleList = (listTypeOrName: string | NodeType, itemTypeOrName: string | NodeType): Command => ({
export const toggleList: Commands['toggleList'] = (listTypeOrName, itemTypeOrName) => ({
editor, tr, state, dispatch, chain, commands, can,
}) => {
const { extensions } = editor.options
@@ -53,3 +53,9 @@ export const toggleList = (listTypeOrName: string | NodeType, itemTypeOrName: st
return commands.wrapInList(listType)
}
declare module '@tiptap/core' {
interface Commands {
toggleList: (listTypeOrName: string | NodeType, itemTypeOrName: string | NodeType) => Command,
}
}

View File

@@ -1,12 +1,12 @@
import { MarkType } from 'prosemirror-model'
import { Command } from '../types'
import { AnyObject, Command, Commands } from '../types'
import getMarkType from '../helpers/getMarkType'
import isMarkActive from '../helpers/isMarkActive'
/**
* Toggle a mark on and off.
*/
export const toggleMark = (typeOrName: string | MarkType, attributes?: {}): Command => ({ state, commands }) => {
export const toggleMark: Commands['toggleMark'] = (typeOrName, attributes = {}) => ({ state, commands }) => {
const type = getMarkType(typeOrName, state.schema)
const isActive = isMarkActive(state, type, attributes)
@@ -16,3 +16,9 @@ export const toggleMark = (typeOrName: string | MarkType, attributes?: {}): Comm
return commands.setMark(type, attributes)
}
declare module '@tiptap/core' {
interface Commands {
toggleMark: (typeOrName: string | MarkType, attributes?: AnyObject) => Command,
}
}

View File

@@ -1,19 +1,25 @@
import { NodeType } from 'prosemirror-model'
import { Command } from '../types'
import { AnyObject, Command, Commands } from '../types'
import isNodeActive from '../helpers/isNodeActive'
import getNodeType from '../helpers/getNodeType'
/**
* Toggle a node with another node.
*/
export const toggleNode = (typeOrName: string | NodeType, toggleTypeOrName: string | NodeType, attrs = {}): Command => ({ state, commands }) => {
export const toggleNode: Commands['toggleNode'] = (typeOrName, toggleTypeOrName, attributes = {}) => ({ state, commands }) => {
const type = getNodeType(typeOrName, state.schema)
const toggleType = getNodeType(toggleTypeOrName, state.schema)
const isActive = isNodeActive(state, type, attrs)
const isActive = isNodeActive(state, type, attributes)
if (isActive) {
return commands.setNode(toggleType)
}
return commands.setNode(type, attrs)
return commands.setNode(type, attributes)
}
declare module '@tiptap/core' {
interface Commands {
toggleNode: (typeOrName: string | NodeType, toggleTypeOrName: string | NodeType, attributes?: AnyObject) => Command,
}
}

View File

@@ -1,13 +1,13 @@
import { wrapIn, lift } from 'prosemirror-commands'
import { NodeType } from 'prosemirror-model'
import { Command } from '../types'
import { AnyObject, Command, Commands } from '../types'
import isNodeActive from '../helpers/isNodeActive'
import getNodeType from '../helpers/getNodeType'
/**
* Wraps nodes in another node, or removes an existing wrap.
*/
export const toggleWrap = (typeOrName: string | NodeType, attributes = {}): Command => ({ state, dispatch }) => {
export const toggleWrap: Commands['toggleWrap'] = (typeOrName, attributes = {}) => ({ state, dispatch }) => {
const type = getNodeType(typeOrName, state.schema)
const isActive = isNodeActive(state, type, attributes)
@@ -17,3 +17,9 @@ export const toggleWrap = (typeOrName: string | NodeType, attributes = {}): Comm
return wrapIn(type, attributes)(state, dispatch)
}
declare module '@tiptap/core' {
interface Commands {
toggleWrap: (typeOrName: string | NodeType, attributes?: AnyObject) => Command,
}
}

View File

@@ -1,9 +1,15 @@
import { undoInputRule as originalUndoInputRule } from 'prosemirror-inputrules'
import { Command } from '../types'
import { Command, Commands } from '../types'
/**
* Undo an input rule.
*/
export const undoInputRule = (): Command => ({ state, dispatch }) => {
export const undoInputRule: Commands['undoInputRule'] = () => ({ state, dispatch }) => {
return originalUndoInputRule(state, dispatch)
}
declare module '@tiptap/core' {
interface Commands {
undoInputRule: () => Command,
}
}

View File

@@ -1,9 +1,9 @@
import { Command } from '../types'
import { Command, Commands } from '../types'
/**
* Remove all marks in the current selection.
*/
export const unsetAllMarks = (): Command => ({ tr, state, dispatch }) => {
export const unsetAllMarks: Commands['unsetAllMarks'] = () => ({ tr, state, dispatch }) => {
const { selection } = tr
const { from, to, empty } = selection
@@ -21,3 +21,9 @@ export const unsetAllMarks = (): Command => ({ tr, state, dispatch }) => {
return true
}
declare module '@tiptap/core' {
interface Commands {
unsetAllMarks: () => Command,
}
}

View File

@@ -1,12 +1,12 @@
import { MarkType } from 'prosemirror-model'
import { Command } from '../types'
import { Command, Commands } from '../types'
import getMarkType from '../helpers/getMarkType'
import getMarkRange from '../helpers/getMarkRange'
/**
* Remove all marks in the current selection.
*/
export const unsetMark = (typeOrName: string | MarkType): Command => ({ tr, state, dispatch }) => {
export const unsetMark: Commands['unsetMark'] = typeOrName => ({ tr, state, dispatch }) => {
const { selection } = tr
const type = getMarkType(typeOrName, state.schema)
let { from, to } = selection
@@ -28,3 +28,9 @@ export const unsetMark = (typeOrName: string | MarkType): Command => ({ tr, stat
return true
}
declare module '@tiptap/core' {
interface Commands {
unsetMark: (typeOrName: string | MarkType) => Command,
}
}

View File

@@ -1,11 +1,11 @@
import { NodeType } from 'prosemirror-model'
import getNodeType from '../helpers/getNodeType'
import { Command } from '../types'
import { AnyObject, Command, Commands } from '../types'
/**
* Update attributes of a node.
*/
export const updateNodeAttributes = (typeOrName: string | NodeType, attributes: {}): Command => ({ tr, state, dispatch }) => {
export const updateNodeAttributes: Commands['updateNodeAttributes'] = (typeOrName, attributes = {}) => ({ tr, state, dispatch }) => {
const type = getNodeType(typeOrName, state.schema)
const { selection } = tr
const { from, to } = selection
@@ -21,3 +21,9 @@ export const updateNodeAttributes = (typeOrName: string | NodeType, attributes:
return true
}
declare module '@tiptap/core' {
interface Commands {
updateNodeAttributes: (typeOrName: string | NodeType, attributes: AnyObject) => Command,
}
}

View File

@@ -1,13 +1,13 @@
import { wrapIn as originalWrapIn } from 'prosemirror-commands'
import { NodeType } from 'prosemirror-model'
import { Command } from '../types'
import { AnyObject, Command, Commands } from '../types'
import isNodeActive from '../helpers/isNodeActive'
import getNodeType from '../helpers/getNodeType'
/**
* Wraps nodes in another node.
*/
export const wrapIn = (typeOrName: string | NodeType, attributes = {}): Command => ({ state, dispatch }) => {
export const wrapIn: Commands['wrapIn'] = (typeOrName, attributes = {}) => ({ state, dispatch }) => {
const type = getNodeType(typeOrName, state.schema)
const isActive = isNodeActive(state, type, attributes)
@@ -17,3 +17,9 @@ export const wrapIn = (typeOrName: string | NodeType, attributes = {}): Command
return originalWrapIn(type, attributes)(state, dispatch)
}
declare module '@tiptap/core' {
interface Commands {
wrapIn: (typeOrName: string | NodeType, attributes?: AnyObject) => Command,
}
}

View File

@@ -1,13 +1,19 @@
import { wrapInList as originalWrapInList } from 'prosemirror-schema-list'
import { NodeType } from 'prosemirror-model'
import { Command } from '../types'
import { AnyObject, Command, Commands } from '../types'
import getNodeType from '../helpers/getNodeType'
/**
* Wrap a node in a list.
*/
export const wrapInList = (typeOrName: string | NodeType, attrs?: {}): Command => ({ state, dispatch }) => {
export const wrapInList: Commands['wrapInList'] = (typeOrName, attributes = {}) => ({ state, dispatch }) => {
const type = getNodeType(typeOrName, state.schema)
return originalWrapInList(type, attrs)(state, dispatch)
return originalWrapInList(type, attributes)(state, dispatch)
}
declare module '@tiptap/core' {
interface Commands {
wrapInList: (typeOrName: string | NodeType, attributes?: AnyObject) => Command,
}
}

View File

@@ -52,9 +52,3 @@ export const ClipboardTextSerializer = Extension.create({
]
},
})
declare module '@tiptap/core' {
interface AllExtensions {
ClipboardTextSerializer: typeof ClipboardTextSerializer,
}
}

View File

@@ -98,9 +98,3 @@ export const Commands = Extension.create({
}
},
})
declare module '@tiptap/core' {
interface AllExtensions {
Commands: typeof Commands,
}
}

View File

@@ -15,9 +15,3 @@ export const Editable = Extension.create({
]
},
})
declare module '@tiptap/core' {
interface AllExtensions {
Editable: typeof Editable,
}
}

View File

@@ -43,9 +43,3 @@ export const FocusEvents = Extension.create({
]
},
})
declare module '@tiptap/core' {
interface AllExtensions {
FocusEvents: typeof FocusEvents,
}
}

View File

@@ -34,9 +34,3 @@ export const Keymap = Extension.create({
}
},
})
declare module '@tiptap/core' {
interface AllExtensions {
Keymap: typeof Keymap,
}
}

View File

@@ -22,3 +22,4 @@ export { default as isCellSelection } from './helpers/isCellSelection'
export { default as findParentNodeClosestToPos } from './helpers/findParentNodeClosestToPos'
export interface AllExtensions {}
export interface Commands {}

View File

@@ -14,7 +14,9 @@ import { Extension } from './Extension'
import { Node } from './Node'
import { Mark } from './Mark'
import { Editor } from './Editor'
import { AllExtensions } from '.'
import { Commands } from '.'
export { Commands }
export type Extensions = (Extension | Node | Mark)[]
@@ -106,29 +108,31 @@ export type NodeViewRendererProps = {
export type NodeViewRenderer = (props: NodeViewRendererProps) => (NodeView | {})
export type UnfilteredCommands = {
[Item in keyof AllExtensions]: AllExtensions[Item] extends Extension<any, infer ExtensionCommands>
? ExtensionCommands
: AllExtensions[Item] extends Node<any, infer NodeCommands>
? NodeCommands
: AllExtensions[Item] extends Mark<any, infer MarkCommands>
? MarkCommands
: never
}
// export type UnfilteredCommands = {
// [Item in keyof AllExtensions]: AllExtensions[Item] extends Extension<any, infer ExtensionCommands>
// ? ExtensionCommands
// : AllExtensions[Item] extends Node<any, infer NodeCommands>
// ? NodeCommands
// : AllExtensions[Item] extends Mark<any, infer MarkCommands>
// ? MarkCommands
// : never
// }
export type ValuesOf<T> = T[keyof T];
export type KeysWithTypeOf<T, Type> = ({[P in keyof T]: T[P] extends Type ? P : never })[keyof T]
export type AllCommands = UnionToIntersection<ValuesOf<Pick<UnfilteredCommands, KeysWithTypeOf<UnfilteredCommands, {}>>>>
// export type Commands = UnionToIntersection<ValuesOf<Pick<UnfilteredCommands, KeysWithTypeOf<UnfilteredCommands, {}>>>>
// export type Commands = Commands
export type SingleCommands = {
[Item in keyof AllCommands]: AllCommands[Item] extends (...args: any[]) => any
? (...args: Parameters<AllCommands[Item]>) => boolean
[Item in keyof Commands]: Commands[Item] extends (...args: any[]) => any
? (...args: Parameters<Commands[Item]>) => boolean
: never
}
export type ChainedCommands = {
[Item in keyof AllCommands]: AllCommands[Item] extends (...args: any[]) => any
? (...args: Parameters<AllCommands[Item]>) => ChainedCommands
[Item in keyof Commands]: Commands[Item] extends (...args: any[]) => any
? (...args: Parameters<Commands[Item]>) => ChainedCommands
: never
} & {
run: () => boolean