add command scope

This commit is contained in:
Philipp Kühn 2021-02-16 11:27:58 +01:00
parent 87beee25b0
commit ca8d1a4245
74 changed files with 614 additions and 460 deletions

View File

@ -14,10 +14,12 @@ export interface AnnotationOptions {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
annotation: {
addAnnotation: (content: any) => Command, addAnnotation: (content: any) => Command,
deleteAnnotation: (id: number) => Command, deleteAnnotation: (id: number) => Command,
} }
}
} }
export const Annotation = Extension.create({ export const Annotation = Extension.create({

View File

@ -8,12 +8,14 @@ export interface IframeOptions {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
iframe: {
/** /**
* Add an iframe * Add an iframe
*/ */
setIframe: (options: { src: string }) => Command, setIframe: (options: { src: string }) => Command,
} }
}
} }
export default Node.create({ export default Node.create({

View File

@ -35,7 +35,8 @@ export default class CommandManager {
.entries(commands) .entries(commands)
.map(([name, command]) => { .map(([name, command]) => {
const method = (...args: any) => { const method = (...args: any) => {
const callback = command(...args)(props) // TODO: fix any
const callback = command(...args as any)(props)
if (!tr.getMeta('preventDispatch')) { if (!tr.getMeta('preventDispatch')) {
view.dispatch(tr) view.dispatch(tr)
@ -85,7 +86,7 @@ export default class CommandManager {
public createCan(startTr?: Transaction): CanCommands { public createCan(startTr?: Transaction): CanCommands {
const { commands, editor } = this const { commands, editor } = this
const { state } = editor const { state } = editor
const dispatch = false const dispatch = undefined
const tr = startTr || state.tr const tr = startTr || state.tr
const props = this.buildProps(tr, dispatch) const props = this.buildProps(tr, dispatch)
const formattedCommands = Object.fromEntries(Object const formattedCommands = Object.fromEntries(Object
@ -118,10 +119,14 @@ export default class CommandManager {
: undefined, : undefined,
chain: () => this.createChain(tr), chain: () => this.createChain(tr),
can: () => this.createCan(tr), can: () => this.createCan(tr),
// TODO: fix
// @ts-ignore
get commands() { get commands() {
return Object.fromEntries(Object return Object.fromEntries(Object
.entries(commands) .entries(commands)
.map(([name, command]) => { .map(([name, command]) => {
// TODO: fix
// @ts-ignore
return [name, (...args: any[]) => command(...args)(props)] return [name, (...args: any[]) => command(...args)(props)]
})) as SingleCommands })) as SingleCommands
}, },

View File

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

View File

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

View File

@ -2,12 +2,14 @@ import { liftTarget } from 'prosemirror-transform'
import { Command, Commands } from '../types' import { Command, Commands } from '../types'
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
clearNodes: {
/** /**
* Normalize nodes to a simple paragraph. * Normalize nodes to a simple paragraph.
*/ */
clearNodes: () => Command, clearNodes: () => Command,
} }
}
} }
export const clearNodes: Commands['clearNodes'] = () => ({ state, tr, dispatch }) => { export const clearNodes: Commands['clearNodes'] = () => ({ state, tr, dispatch }) => {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -5,12 +5,14 @@ import getMarkType from '../helpers/getMarkType'
import getMarkRange from '../helpers/getMarkRange' import getMarkRange from '../helpers/getMarkRange'
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
extendMarkRange: {
/** /**
* Extends the text selection to the current mark. * Extends the text selection to the current mark.
*/ */
extendMarkRange: (typeOrName: string | MarkType) => Command, extendMarkRange: (typeOrName: string | MarkType) => Command,
} }
}
} }
export const extendMarkRange: Commands['extendMarkRange'] = typeOrName => ({ tr, state, dispatch }) => { export const extendMarkRange: Commands['extendMarkRange'] = typeOrName => ({ tr, state, dispatch }) => {

View File

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

View File

@ -31,12 +31,14 @@ function resolveSelection(state: EditorState, position: FocusPosition = null) {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
focus: {
/** /**
* Focus the editor at the given position. * Focus the editor at the given position.
*/ */
focus: (position?: FocusPosition) => Command, focus: (position?: FocusPosition) => Command,
} }
}
} }
export const focus: Commands['focus'] = (position = null) => ({ export const focus: Commands['focus'] = (position = null) => ({

View File

@ -18,12 +18,14 @@ function selectionToInsertionEnd(tr: Transaction, startLen: number, bias: number
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
insertHTML: {
/** /**
* Insert a string of HTML at the current position. * Insert a string of HTML at the current position.
*/ */
insertHTML: (value: string) => Command, insertHTML: (value: string) => Command,
} }
}
} }
export const insertHTML: Commands['insertHTML'] = value => ({ tr, state, dispatch }) => { export const insertHTML: Commands['insertHTML'] = value => ({ tr, state, dispatch }) => {

View File

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

View File

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

View File

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

View File

@ -57,12 +57,14 @@ function normalizeKeyName(name: string) {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
keyboardShortcut: {
/** /**
* Trigger a keyboard shortcut. * Trigger a keyboard shortcut.
*/ */
keyboardShortcut: (name: string) => Command, keyboardShortcut: (name: string) => Command,
} }
}
} }
export const keyboardShortcut: Commands['keyboardShortcut'] = name => ({ export const keyboardShortcut: Commands['keyboardShortcut'] = name => ({

View File

@ -5,12 +5,14 @@ import isNodeActive from '../helpers/isNodeActive'
import getNodeType from '../helpers/getNodeType' import getNodeType from '../helpers/getNodeType'
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
lift: {
/** /**
* Removes an existing wrap. * Removes an existing wrap.
*/ */
lift: (typeOrName: string | NodeType, attributes?: AnyObject) => Command, lift: (typeOrName: string | NodeType, attributes?: AnyObject) => Command,
} }
}
} }
export const lift: Commands['lift'] = (typeOrName, attributes = {}) => ({ state, dispatch }) => { export const lift: Commands['lift'] = (typeOrName, attributes = {}) => ({ state, dispatch }) => {

View File

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

View File

@ -4,12 +4,14 @@ import { Command, Commands } from '../types'
import getNodeType from '../helpers/getNodeType' import getNodeType from '../helpers/getNodeType'
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
liftListItem: {
/** /**
* Lift the list item into a wrapping list. * Lift the list item into a wrapping list.
*/ */
liftListItem: (typeOrName: string | NodeType) => Command, liftListItem: (typeOrName: string | NodeType) => Command,
} }
}
} }
export const liftListItem: Commands['liftListItem'] = typeOrName => ({ state, dispatch }) => { export const liftListItem: Commands['liftListItem'] = typeOrName => ({ state, dispatch }) => {

View File

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

View File

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

View File

@ -8,12 +8,14 @@ import {
} from '../types' } from '../types'
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
replaceRange: {
/** /**
* Replaces text with a node within a range. * Replaces text with a node within a range.
*/ */
replaceRange: (range: Range, typeOrName: string | NodeType, attributes?: AnyObject) => Command, replaceRange: (range: Range, typeOrName: string | NodeType, attributes?: AnyObject) => Command,
} }
}
} }
export const replaceRange: Commands['replaceRange'] = (range, typeOrName, attributes = {}) => ({ tr, state, dispatch }) => { export const replaceRange: Commands['replaceRange'] = (range, typeOrName, attributes = {}) => ({ tr, state, dispatch }) => {

View File

@ -4,12 +4,14 @@ import deleteProps from '../utilities/deleteProps'
import { Command, Commands } from '../types' import { Command, Commands } from '../types'
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
resetNodeAttributes: {
/** /**
* Resets node attributes to the default value. * Resets node attributes to the default value.
*/ */
resetNodeAttributes: (typeOrName: string | NodeType, attributes: string | string[]) => Command, resetNodeAttributes: (typeOrName: string | NodeType, attributes: string | string[]) => Command,
} }
}
} }
export const resetNodeAttributes: Commands['resetNodeAttributes'] = (typeOrName, attributes) => ({ tr, state, dispatch }) => { export const resetNodeAttributes: Commands['resetNodeAttributes'] = (typeOrName, attributes) => ({ tr, state, dispatch }) => {

View File

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

View File

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

View File

@ -2,12 +2,14 @@ import { selectNodeBackward as originalSelectNodeBackward } from 'prosemirror-co
import { Command, Commands } from '../types' import { Command, Commands } from '../types'
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
selectNodeBackward: {
/** /**
* Select a node backward. * Select a node backward.
*/ */
selectNodeBackward: () => Command, selectNodeBackward: () => Command,
} }
}
} }
export const selectNodeBackward: Commands['selectNodeBackward'] = () => ({ state, dispatch }) => { export const selectNodeBackward: Commands['selectNodeBackward'] = () => ({ state, dispatch }) => {

View File

@ -2,12 +2,14 @@ import { selectNodeForward as originalSelectNodeForward } from 'prosemirror-comm
import { Command, Commands } from '../types' import { Command, Commands } from '../types'
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
selectNodeForward: {
/** /**
* Select a node forward. * Select a node forward.
*/ */
selectNodeForward: () => Command, selectNodeForward: () => Command,
} }
}
} }
export const selectNodeForward: Commands['selectNodeForward'] = () => ({ state, dispatch }) => { export const selectNodeForward: Commands['selectNodeForward'] = () => ({ state, dispatch }) => {

View File

@ -2,12 +2,14 @@ import { selectParentNode as originalSelectParentNode } from 'prosemirror-comman
import { Command, Commands } from '../types' import { Command, Commands } from '../types'
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
selectParentNode: {
/** /**
* Select the parent node. * Select the parent node.
*/ */
selectParentNode: () => Command, selectParentNode: () => Command,
} }
}
} }
export const selectParentNode: Commands['selectParentNode'] = () => ({ state, dispatch }) => { export const selectParentNode: Commands['selectParentNode'] = () => ({ state, dispatch }) => {

View File

@ -2,12 +2,14 @@ import { TextSelection } from 'prosemirror-state'
import { AnyObject, Command, Commands } from '../types' import { AnyObject, Command, Commands } from '../types'
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
setContent: {
/** /**
* Replace the whole document with new content. * Replace the whole document with new content.
*/ */
setContent: (content: string, emitUpdate?: Boolean, parseOptions?: AnyObject) => Command, setContent: (content: string, emitUpdate?: Boolean, parseOptions?: AnyObject) => Command,
} }
}
} }
export const setContent: Commands['setContent'] = (content, emitUpdate = false, parseOptions = {}) => ({ tr, editor, dispatch }) => { export const setContent: Commands['setContent'] = (content, emitUpdate = false, parseOptions = {}) => ({ tr, editor, dispatch }) => {

View File

@ -4,12 +4,14 @@ import getMarkType from '../helpers/getMarkType'
import getMarkAttributes from '../helpers/getMarkAttributes' import getMarkAttributes from '../helpers/getMarkAttributes'
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
setMark: {
/** /**
* Add a mark with new attributes. * Add a mark with new attributes.
*/ */
setMark: (typeOrName: string | MarkType, attributes?: AnyObject) => Command, setMark: (typeOrName: string | MarkType, attributes?: AnyObject) => Command,
} }
}
} }
export const setMark: Commands['setMark'] = (typeOrName, attributes = {}) => ({ tr, state, dispatch }) => { export const setMark: Commands['setMark'] = (typeOrName, attributes = {}) => ({ tr, state, dispatch }) => {

View File

@ -4,12 +4,14 @@ import { AnyObject, Command, Commands } from '../types'
import getNodeType from '../helpers/getNodeType' import getNodeType from '../helpers/getNodeType'
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
setNode: {
/** /**
* Replace a given range with a node. * Replace a given range with a node.
*/ */
setNode: (typeOrName: string | NodeType, attributes?: AnyObject) => Command, setNode: (typeOrName: string | NodeType, attributes?: AnyObject) => Command,
} }
}
} }
export const setNode: Commands['setNode'] = (typeOrName, attributes = {}) => ({ state, dispatch }) => { export const setNode: Commands['setNode'] = (typeOrName, attributes = {}) => ({ state, dispatch }) => {

View File

@ -4,12 +4,14 @@ import { Command, Commands } from '../types'
import getNodeType from '../helpers/getNodeType' import getNodeType from '../helpers/getNodeType'
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
sinkListItem: {
/** /**
* Sink the list item down into an inner list. * Sink the list item down into an inner list.
*/ */
sinkListItem: (typeOrName: string | NodeType) => Command, sinkListItem: (typeOrName: string | NodeType) => Command,
} }
}
} }
export const sinkListItem: Commands['sinkListItem'] = typeOrName => ({ state, dispatch }) => { export const sinkListItem: Commands['sinkListItem'] = typeOrName => ({ state, dispatch }) => {

View File

@ -25,12 +25,14 @@ function ensureMarks(state: EditorState) {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
splitBlock: {
/** /**
* Forks a new node from an existing node. * Forks a new node from an existing node.
*/ */
splitBlock: (options?: { keepMarks?: boolean }) => Command, splitBlock: (options?: { keepMarks?: boolean }) => Command,
} }
}
} }
export const splitBlock: Commands['splitBlock'] = ({ keepMarks = true } = {}) => ({ export const splitBlock: Commands['splitBlock'] = ({ keepMarks = true } = {}) => ({

View File

@ -11,12 +11,14 @@ import getNodeType from '../helpers/getNodeType'
import getSplittedAttributes from '../helpers/getSplittedAttributes' import getSplittedAttributes from '../helpers/getSplittedAttributes'
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
splitListItem: {
/** /**
* Splits one list item into two list items. * Splits one list item into two list items.
*/ */
splitListItem: (typeOrName: string | NodeType) => Command, splitListItem: (typeOrName: string | NodeType) => Command,
} }
}
} }
export const splitListItem: Commands['splitListItem'] = typeOrName => ({ export const splitListItem: Commands['splitListItem'] = typeOrName => ({

View File

@ -5,12 +5,14 @@ import findParentNode from '../helpers/findParentNode'
import isList from '../helpers/isList' import isList from '../helpers/isList'
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
toggleList: {
/** /**
* Toggle between different list types. * Toggle between different list types.
*/ */
toggleList: (listTypeOrName: string | NodeType, itemTypeOrName: string | NodeType) => Command, toggleList: (listTypeOrName: string | NodeType, itemTypeOrName: string | NodeType) => Command,
} }
}
} }
export const toggleList: Commands['toggleList'] = (listTypeOrName, itemTypeOrName) => ({ export const toggleList: Commands['toggleList'] = (listTypeOrName, itemTypeOrName) => ({

View File

@ -4,12 +4,14 @@ import getMarkType from '../helpers/getMarkType'
import isMarkActive from '../helpers/isMarkActive' import isMarkActive from '../helpers/isMarkActive'
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
toggleMark: {
/** /**
* Toggle a mark on and off. * Toggle a mark on and off.
*/ */
toggleMark: (typeOrName: string | MarkType, attributes?: AnyObject) => Command, toggleMark: (typeOrName: string | MarkType, attributes?: AnyObject) => Command,
} }
}
} }
export const toggleMark: Commands['toggleMark'] = (typeOrName, attributes = {}) => ({ state, commands }) => { export const toggleMark: Commands['toggleMark'] = (typeOrName, attributes = {}) => ({ state, commands }) => {

View File

@ -4,12 +4,14 @@ import isNodeActive from '../helpers/isNodeActive'
import getNodeType from '../helpers/getNodeType' import getNodeType from '../helpers/getNodeType'
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
toggleNode: {
/** /**
* Toggle a node with another node. * Toggle a node with another node.
*/ */
toggleNode: (typeOrName: string | NodeType, toggleTypeOrName: string | NodeType, attributes?: AnyObject) => Command, toggleNode: (typeOrName: string | NodeType, toggleTypeOrName: string | NodeType, attributes?: AnyObject) => Command,
} }
}
} }
export const toggleNode: Commands['toggleNode'] = (typeOrName, toggleTypeOrName, attributes = {}) => ({ state, commands }) => { export const toggleNode: Commands['toggleNode'] = (typeOrName, toggleTypeOrName, attributes = {}) => ({ state, commands }) => {

View File

@ -5,12 +5,14 @@ import isNodeActive from '../helpers/isNodeActive'
import getNodeType from '../helpers/getNodeType' import getNodeType from '../helpers/getNodeType'
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
toggleWrap: {
/** /**
* Wraps nodes in another node, or removes an existing wrap. * Wraps nodes in another node, or removes an existing wrap.
*/ */
toggleWrap: (typeOrName: string | NodeType, attributes?: AnyObject) => Command, toggleWrap: (typeOrName: string | NodeType, attributes?: AnyObject) => Command,
} }
}
} }
export const toggleWrap: Commands['toggleWrap'] = (typeOrName, attributes = {}) => ({ state, dispatch }) => { export const toggleWrap: Commands['toggleWrap'] = (typeOrName, attributes = {}) => ({ state, dispatch }) => {

View File

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

View File

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

View File

@ -4,12 +4,14 @@ import getMarkType from '../helpers/getMarkType'
import getMarkRange from '../helpers/getMarkRange' import getMarkRange from '../helpers/getMarkRange'
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
unsetMark: {
/** /**
* Remove all marks in the current selection. * Remove all marks in the current selection.
*/ */
unsetMark: (typeOrName: string | MarkType) => Command, unsetMark: (typeOrName: string | MarkType) => Command,
} }
}
} }
export const unsetMark: Commands['unsetMark'] = typeOrName => ({ tr, state, dispatch }) => { export const unsetMark: Commands['unsetMark'] = typeOrName => ({ tr, state, dispatch }) => {

View File

@ -3,12 +3,14 @@ import getNodeType from '../helpers/getNodeType'
import { AnyObject, Command, Commands } from '../types' import { AnyObject, Command, Commands } from '../types'
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
updateNodeAttributes: {
/** /**
* Update attributes of a node. * Update attributes of a node.
*/ */
updateNodeAttributes: (typeOrName: string | NodeType, attributes: AnyObject) => Command, updateNodeAttributes: (typeOrName: string | NodeType, attributes: AnyObject) => Command,
} }
}
} }
export const updateNodeAttributes: Commands['updateNodeAttributes'] = (typeOrName, attributes = {}) => ({ tr, state, dispatch }) => { export const updateNodeAttributes: Commands['updateNodeAttributes'] = (typeOrName, attributes = {}) => ({ tr, state, dispatch }) => {

View File

@ -5,12 +5,14 @@ import isNodeActive from '../helpers/isNodeActive'
import getNodeType from '../helpers/getNodeType' import getNodeType from '../helpers/getNodeType'
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
wrapIn: {
/** /**
* Wraps nodes in another node. * Wraps nodes in another node.
*/ */
wrapIn: (typeOrName: string | NodeType, attributes?: AnyObject) => Command, wrapIn: (typeOrName: string | NodeType, attributes?: AnyObject) => Command,
} }
}
} }
export const wrapIn: Commands['wrapIn'] = (typeOrName, attributes = {}) => ({ state, dispatch }) => { export const wrapIn: Commands['wrapIn'] = (typeOrName, attributes = {}) => ({ state, dispatch }) => {

View File

@ -4,12 +4,14 @@ import { AnyObject, Command, Commands } from '../types'
import getNodeType from '../helpers/getNodeType' import getNodeType from '../helpers/getNodeType'
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
wrapInList: {
/** /**
* Wrap a node in a list. * Wrap a node in a list.
*/ */
wrapInList: (typeOrName: string | NodeType, attributes?: AnyObject) => Command, wrapInList: (typeOrName: string | NodeType, attributes?: AnyObject) => Command,
} }
}
} }
export const wrapInList: Commands['wrapInList'] = (typeOrName, attributes = {}) => ({ state, dispatch }) => { export const wrapInList: Commands['wrapInList'] = (typeOrName, attributes = {}) => ({ state, dispatch }) => {

View File

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

View File

@ -14,9 +14,9 @@ import { Extension } from './Extension'
import { Node } from './Node' import { Node } from './Node'
import { Mark } from './Mark' import { Mark } from './Mark'
import { Editor } from './Editor' import { Editor } from './Editor'
import { Commands } from '.' import { AllCommands } from '.'
export { Commands } export { AllCommands }
export type Extensions = (Extension | Node | Mark)[] export type Extensions = (Extension | Node | Mark)[]
@ -120,6 +120,13 @@ export type NodeViewRenderer = (props: NodeViewRendererProps) => (NodeView | {})
export type ValuesOf<T> = T[keyof T]; 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 KeysWithTypeOf<T, Type> = ({[P in keyof T]: T[P] extends Type ? P : never })[keyof T]
export type UnionCommands = UnionToIntersection<ValuesOf<Pick<AllCommands, KeysWithTypeOf<AllCommands, {}>>>>
export type Commands = {
[Item in keyof UnionCommands]: UnionCommands[Item] extends (...args: any[]) => any
? (...args: Parameters<UnionCommands[Item]>) => Command
: never
}
export type SingleCommands = { export type SingleCommands = {
[Item in keyof Commands]: Commands[Item] extends (...args: any[]) => any [Item in keyof Commands]: Commands[Item] extends (...args: any[]) => any

View File

@ -8,7 +8,8 @@ export interface BlockquoteOptions {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
blockQuote: {
/** /**
* Set a blockquote node * Set a blockquote node
*/ */
@ -22,6 +23,7 @@ declare module '@tiptap/core' {
*/ */
unsetBlockquote: () => Command, unsetBlockquote: () => Command,
} }
}
} }
export const inputRegex = /^\s*>\s$/gm export const inputRegex = /^\s*>\s$/gm

View File

@ -13,7 +13,8 @@ export interface BoldOptions {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
bold: {
/** /**
* Set a bold mark * Set a bold mark
*/ */
@ -27,6 +28,7 @@ declare module '@tiptap/core' {
*/ */
unsetBold: () => Command, unsetBold: () => Command,
} }
}
} }
export const starInputRegex = /(?:^|\s)((?:\*\*)((?:[^*]+))(?:\*\*))$/gm export const starInputRegex = /(?:^|\s)((?:\*\*)((?:[^*]+))(?:\*\*))$/gm

View File

@ -8,12 +8,14 @@ export interface BulletListOptions {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
bulletList: {
/** /**
* Toggle a bullet list * Toggle a bullet list
*/ */
toggleBulletList: () => Command, toggleBulletList: () => Command,
} }
}
} }
export const inputRegex = /^\s*([-+*])\s$/ export const inputRegex = /^\s*([-+*])\s$/

View File

@ -9,7 +9,8 @@ export interface CodeBlockOptions {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
codeBlock: {
/** /**
* Set a code block * Set a code block
*/ */
@ -19,6 +20,7 @@ declare module '@tiptap/core' {
*/ */
toggleCodeBlock: (attributes?: { language: string }) => Command, toggleCodeBlock: (attributes?: { language: string }) => Command,
} }
}
} }
export const backtickInputRegex = /^```(?<language>[a-z]*)? $/ export const backtickInputRegex = /^```(?<language>[a-z]*)? $/

View File

@ -13,7 +13,8 @@ export interface CodeOptions {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
code: {
/** /**
* Set a code mark * Set a code mark
*/ */
@ -27,6 +28,7 @@ declare module '@tiptap/core' {
*/ */
unsetCode: () => Command, unsetCode: () => Command,
} }
}
} }
export const inputRegex = /(?:^|\s)((?:`)((?:[^`]+))(?:`))$/gm export const inputRegex = /(?:^|\s)((?:`)((?:[^`]+))(?:`))$/gm

View File

@ -9,12 +9,14 @@ export interface CollaborationCursorOptions {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
collaborationCursor: {
/** /**
* Update details of the current user * Update details of the current user
*/ */
user: (attributes: AnyObject) => Command, user: (attributes: AnyObject) => Command,
} }
}
} }
const awarenessStatesToArray = (states: Map<number, { [key: string]: any }>) => { const awarenessStatesToArray = (states: Map<number, { [key: string]: any }>) => {

View File

@ -7,7 +7,8 @@ import {
} from 'y-prosemirror' } from 'y-prosemirror'
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
collaboration: {
/** /**
* Undo recent changes * Undo recent changes
*/ */
@ -17,6 +18,7 @@ declare module '@tiptap/core' {
*/ */
redo: () => Command, redo: () => Command,
} }
}
} }
export interface CollaborationOptions { export interface CollaborationOptions {

View File

@ -6,7 +6,8 @@ type FontFamilyOptions = {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
fontFamily: {
/** /**
* Set the font family * Set the font family
*/ */
@ -16,6 +17,7 @@ declare module '@tiptap/core' {
*/ */
unsetFontFamily: () => Command, unsetFontFamily: () => Command,
} }
}
} }
export const FontFamily = Extension.create<FontFamilyOptions>({ export const FontFamily = Extension.create<FontFamilyOptions>({

View File

@ -8,12 +8,14 @@ export interface HardBreakOptions {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
hardBreak: {
/** /**
* Add a hard break * Add a hard break
*/ */
setHardBreak: () => Command, setHardBreak: () => Command,
} }
}
} }
export const HardBreak = Node.create<HardBreakOptions>({ export const HardBreak = Node.create<HardBreakOptions>({

View File

@ -11,7 +11,8 @@ export interface HeadingOptions {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
heading: {
/** /**
* Set a heading node * Set a heading node
*/ */
@ -21,6 +22,7 @@ declare module '@tiptap/core' {
*/ */
toggleHeading: (attributes: { level: Level }) => Command, toggleHeading: (attributes: { level: Level }) => Command,
} }
}
} }
export const Heading = Node.create<HeadingOptions>({ export const Heading = Node.create<HeadingOptions>({

View File

@ -14,7 +14,8 @@ export interface HighlightOptions {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
highlight: {
/** /**
* Set a highlight mark * Set a highlight mark
*/ */
@ -28,6 +29,7 @@ declare module '@tiptap/core' {
*/ */
unsetHighlight: () => Command, unsetHighlight: () => Command,
} }
}
} }
export const inputRegex = /(?:^|\s)((?:==)((?:[^~]+))(?:==))$/gm export const inputRegex = /(?:^|\s)((?:==)((?:[^~]+))(?:==))$/gm

View File

@ -7,7 +7,8 @@ export interface HistoryOptions {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
history: {
/** /**
* Undo recent changes * Undo recent changes
*/ */
@ -17,6 +18,7 @@ declare module '@tiptap/core' {
*/ */
redo: () => Command, redo: () => Command,
} }
}
} }
export const History = Extension.create<HistoryOptions>({ export const History = Extension.create<HistoryOptions>({

View File

@ -12,12 +12,14 @@ export interface HorizontalRuleOptions {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
horizontalRule: {
/** /**
* Add a horizontal rule * Add a horizontal rule
*/ */
setHorizontalRule: () => Command, setHorizontalRule: () => Command,
} }
}
} }
export const HorizontalRule = Node.create<HorizontalRuleOptions>({ export const HorizontalRule = Node.create<HorizontalRuleOptions>({

View File

@ -13,12 +13,14 @@ export interface ImageOptions {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
image: {
/** /**
* Add an image * Add an image
*/ */
setImage: (options: { src: string, alt?: string, title?: string }) => Command, setImage: (options: { src: string, alt?: string, title?: string }) => Command,
} }
}
} }
export const inputRegex = /!\[(.+|:?)]\((\S+)(?:(?:\s+)["'](\S+)["'])?\)/ export const inputRegex = /!\[(.+|:?)]\((\S+)(?:(?:\s+)["'](\S+)["'])?\)/

View File

@ -13,7 +13,8 @@ export interface ItalicOptions {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
italic: {
/** /**
* Set an italic mark * Set an italic mark
*/ */
@ -27,6 +28,7 @@ declare module '@tiptap/core' {
*/ */
unsetItalic: () => Command, unsetItalic: () => Command,
} }
}
} }
export const starInputRegex = /(?:^|\s)((?:\*)((?:[^*]+))(?:\*))$/gm export const starInputRegex = /(?:^|\s)((?:\*)((?:[^*]+))(?:\*))$/gm

View File

@ -14,7 +14,8 @@ export interface LinkOptions {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
link: {
/** /**
* Set a link mark * Set a link mark
*/ */
@ -28,6 +29,7 @@ declare module '@tiptap/core' {
*/ */
unsetLink: () => Command, unsetLink: () => Command,
} }
}
} }
export const pasteRegex = /https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z]{2,}\b(?:[-a-zA-Z0-9@:%._+~#=?!&/]*)(?:[-a-zA-Z0-9@:%._+~#=?!&/]*)/gi export const pasteRegex = /https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z]{2,}\b(?:[-a-zA-Z0-9@:%._+~#=?!&/]*)(?:[-a-zA-Z0-9@:%._+~#=?!&/]*)/gi

View File

@ -8,12 +8,14 @@ export interface OrderedListOptions {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
orderedList: {
/** /**
* Toggle an ordered list * Toggle an ordered list
*/ */
toggleOrderedList: () => Command, toggleOrderedList: () => Command,
} }
}
} }
export const inputRegex = /^(\d+)\.\s$/ export const inputRegex = /^(\d+)\.\s$/

View File

@ -7,12 +7,14 @@ export interface ParagraphOptions {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
paragraph: {
/** /**
* Toggle a paragraph * Toggle a paragraph
*/ */
setParagraph: () => Command, setParagraph: () => Command,
} }
}
} }
export const Paragraph = Node.create<ParagraphOptions>({ export const Paragraph = Node.create<ParagraphOptions>({

View File

@ -13,7 +13,8 @@ export interface StrikeOptions {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
strike: {
/** /**
* Set a strike mark * Set a strike mark
*/ */
@ -27,6 +28,7 @@ declare module '@tiptap/core' {
*/ */
unsetStrike: () => Command, unsetStrike: () => Command,
} }
}
} }
export const inputRegex = /(?:^|\s)((?:~~)((?:[^~]+))(?:~~))$/gm export const inputRegex = /(?:^|\s)((?:~~)((?:[^~]+))(?:~~))$/gm

View File

@ -42,7 +42,8 @@ export interface TableOptions {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
table: {
insertTable: (options?: { rows?: number, cols?: number, withHeaderRow?: boolean }) => Command, insertTable: (options?: { rows?: number, cols?: number, withHeaderRow?: boolean }) => Command,
addColumnBefore: () => Command, addColumnBefore: () => Command,
addColumnAfter: () => Command, addColumnAfter: () => Command,
@ -62,6 +63,7 @@ declare module '@tiptap/core' {
goToPreviousCell: () => Command, goToPreviousCell: () => Command,
fixTables: () => Command, fixTables: () => Command,
} }
}
} }
export const Table = Node.create<TableOptions>({ export const Table = Node.create<TableOptions>({

View File

@ -7,12 +7,14 @@ export interface TaskListOptions {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
taskList: {
/** /**
* Toggle a task list * Toggle a task list
*/ */
toggleTaskList: () => Command, toggleTaskList: () => Command,
} }
}
} }
export const TaskList = Node.create<TaskListOptions>({ export const TaskList = Node.create<TaskListOptions>({

View File

@ -7,7 +7,8 @@ type TextAlignOptions = {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
textAlign: {
/** /**
* Set the text align attribute * Set the text align attribute
*/ */
@ -17,6 +18,7 @@ declare module '@tiptap/core' {
*/ */
unsetTextAlign: () => Command, unsetTextAlign: () => Command,
} }
}
} }
export const TextAlign = Extension.create<TextAlignOptions>({ export const TextAlign = Extension.create<TextAlignOptions>({

View File

@ -12,12 +12,14 @@ export interface TextStyleOptions {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
textStyle: {
/** /**
* Remove spans without inline style attributes. * Remove spans without inline style attributes.
*/ */
removeEmptyTextStyle: () => Command, removeEmptyTextStyle: () => Command,
} }
}
} }
export const TextStyle = Mark.create<TextStyleOptions>({ export const TextStyle = Mark.create<TextStyleOptions>({

View File

@ -7,7 +7,8 @@ export interface UnderlineOptions {
} }
declare module '@tiptap/core' { declare module '@tiptap/core' {
interface Commands { interface AllCommands {
underline: {
/** /**
* Set an underline mark * Set an underline mark
*/ */
@ -21,6 +22,7 @@ declare module '@tiptap/core' {
*/ */
unsetUnderline: () => Command, unsetUnderline: () => Command,
} }
}
} }
export const Underline = Mark.create<UnderlineOptions>({ export const Underline = Mark.create<UnderlineOptions>({