2020-10-23 05:21:52 +08:00
import {
2020-11-16 18:19:43 +08:00
DOMOutputSpec ,
Mark as ProseMirrorMark ,
2022-06-08 20:10:25 +08:00
MarkSpec ,
2020-11-16 18:19:43 +08:00
MarkType ,
2020-10-23 05:21:52 +08:00
} from 'prosemirror-model'
2020-11-30 21:12:36 +08:00
import { Plugin , Transaction } from 'prosemirror-state'
2022-06-08 20:10:25 +08:00
import { MarkConfig } from '.'
import { Editor } from './Editor'
import { getExtensionField } from './helpers/getExtensionField'
2021-10-08 21:02:09 +08:00
import { InputRule } from './InputRule'
2022-06-08 20:10:25 +08:00
import { Node } from './Node'
2021-10-08 21:02:09 +08:00
import { PasteRule } from './PasteRule'
2021-04-12 17:11:02 +08:00
import {
2021-10-22 14:52:54 +08:00
AnyConfig ,
2021-04-12 17:11:02 +08:00
Attributes ,
2022-06-08 20:10:25 +08:00
Extensions ,
2021-04-12 17:11:02 +08:00
GlobalAttributes ,
2021-04-21 04:58:09 +08:00
KeyboardShortcutCommand ,
2022-06-08 20:10:25 +08:00
ParentConfig ,
RawCommands ,
2021-04-12 17:11:02 +08:00
} from './types'
2022-06-08 20:10:25 +08:00
import { callOrReturn } from './utilities/callOrReturn'
import { mergeDeep } from './utilities/mergeDeep'
2020-10-22 03:13:38 +08:00
2021-02-20 00:35:50 +08:00
declare module '@tiptap/core' {
2021-10-22 14:52:54 +08:00
export interface MarkConfig < Options = any , Storage = any > {
2021-02-20 00:47:22 +08:00
[ key : string ] : any ;
2021-02-20 00:35:50 +08:00
/ * *
* Name
* /
name : string ,
2021-04-08 00:29:16 +08:00
/ * *
* Priority
* /
priority? : number ,
2021-02-20 00:35:50 +08:00
/ * *
* Default options
* /
defaultOptions? : Options ,
2021-10-27 00:31:13 +08:00
/ * *
* Default Options
* /
addOptions ? : ( this : {
name : string ,
parent : Exclude < ParentConfig < MarkConfig < Options , Storage > > [ 'addOptions' ] , undefined > ,
} ) = > Options ,
2021-10-22 14:52:54 +08:00
/ * *
* Default Storage
* /
2021-10-27 00:31:13 +08:00
addStorage ? : ( this : {
2021-10-22 14:52:54 +08:00
name : string ,
options : Options ,
2021-10-27 00:31:13 +08:00
parent : Exclude < ParentConfig < MarkConfig < Options , Storage > > [ 'addStorage' ] , undefined > ,
2021-10-22 14:52:54 +08:00
} ) = > Storage ,
2021-02-20 00:35:50 +08:00
/ * *
* Global attributes
* /
addGlobalAttributes ? : ( this : {
2021-04-21 05:11:35 +08:00
name : string ,
2020-10-22 03:13:38 +08:00
options : Options ,
2021-10-22 14:52:54 +08:00
storage : Storage ,
parent : ParentConfig < MarkConfig < Options , Storage > > [ 'addGlobalAttributes' ] ,
2021-02-20 00:35:50 +08:00
} ) = > GlobalAttributes | { } ,
2020-10-23 05:21:52 +08:00
2021-02-20 00:35:50 +08:00
/ * *
* Raw
* /
addCommands ? : ( this : {
2021-04-21 05:11:35 +08:00
name : string ,
2020-10-22 03:13:38 +08:00
options : Options ,
2021-10-22 14:52:54 +08:00
storage : Storage ,
2021-02-20 00:35:50 +08:00
editor : Editor ,
type : MarkType ,
2021-10-22 14:52:54 +08:00
parent : ParentConfig < MarkConfig < Options , Storage > > [ 'addCommands' ] ,
2021-02-20 00:35:50 +08:00
} ) = > Partial < RawCommands > ,
2020-10-23 05:21:52 +08:00
2021-02-20 00:35:50 +08:00
/ * *
* Keyboard shortcuts
* /
addKeyboardShortcuts ? : ( this : {
2021-04-21 05:11:35 +08:00
name : string ,
2020-10-22 05:55:14 +08:00
options : Options ,
2021-10-22 14:52:54 +08:00
storage : Storage ,
2021-02-20 00:35:50 +08:00
editor : Editor ,
type : MarkType ,
2021-10-22 14:52:54 +08:00
parent : ParentConfig < MarkConfig < Options , Storage > > [ 'addKeyboardShortcuts' ] ,
2021-02-20 00:35:50 +08:00
} ) = > {
2021-04-21 04:58:09 +08:00
[ key : string ] : KeyboardShortcutCommand ,
2020-10-22 05:55:14 +08:00
} ,
2021-02-20 00:35:50 +08:00
/ * *
* Input rules
* /
addInputRules ? : ( this : {
2021-04-21 05:11:35 +08:00
name : string ,
2020-11-30 21:12:36 +08:00
options : Options ,
2021-10-22 14:52:54 +08:00
storage : Storage ,
2020-11-30 21:12:36 +08:00
editor : Editor ,
type : MarkType ,
2021-10-22 14:52:54 +08:00
parent : ParentConfig < MarkConfig < Options , Storage > > [ 'addInputRules' ] ,
2021-02-20 00:35:50 +08:00
} ) = > InputRule [ ] ,
2020-11-30 21:12:36 +08:00
2021-02-20 00:35:50 +08:00
/ * *
* Paste rules
* /
addPasteRules ? : ( this : {
2021-04-21 05:11:35 +08:00
name : string ,
2020-11-30 21:12:36 +08:00
options : Options ,
2021-10-22 14:52:54 +08:00
storage : Storage ,
2020-11-30 21:12:36 +08:00
editor : Editor ,
type : MarkType ,
2021-10-22 14:52:54 +08:00
parent : ParentConfig < MarkConfig < Options , Storage > > [ 'addPasteRules' ] ,
2021-10-08 21:02:09 +08:00
} ) = > PasteRule [ ] ,
2020-11-30 21:12:36 +08:00
2021-02-20 00:35:50 +08:00
/ * *
* ProseMirror plugins
* /
addProseMirrorPlugins ? : ( this : {
2021-04-21 05:11:35 +08:00
name : string ,
2020-11-30 21:12:36 +08:00
options : Options ,
2021-10-22 14:52:54 +08:00
storage : Storage ,
2020-11-30 21:12:36 +08:00
editor : Editor ,
type : MarkType ,
2021-10-22 14:52:54 +08:00
parent : ParentConfig < MarkConfig < Options , Storage > > [ 'addProseMirrorPlugins' ] ,
2021-02-20 00:35:50 +08:00
} ) = > Plugin [ ] ,
2021-05-07 00:39:47 +08:00
/ * *
* Extensions
* /
addExtensions ? : ( this : {
name : string ,
options : Options ,
2021-10-22 14:52:54 +08:00
storage : Storage ,
parent : ParentConfig < MarkConfig < Options , Storage > > [ 'addExtensions' ] ,
2021-05-07 16:08:30 +08:00
} ) = > Extensions ,
2021-05-07 00:39:47 +08:00
2021-02-20 00:35:50 +08:00
/ * *
* Extend Node Schema
* /
extendNodeSchema ? : ( (
this : {
2021-04-21 05:11:35 +08:00
name : string ,
2021-02-20 00:35:50 +08:00
options : Options ,
2021-10-22 14:52:54 +08:00
storage : Storage ,
parent : ParentConfig < MarkConfig < Options , Storage > > [ 'extendNodeSchema' ] ,
2021-02-20 00:35:50 +08:00
} ,
extension : Node ,
2021-04-21 15:43:31 +08:00
) = > Record < string , any > ) | null ,
2021-02-20 00:35:50 +08:00
/ * *
* Extend Mark Schema
* /
extendMarkSchema ? : ( (
this : {
2021-04-21 05:11:35 +08:00
name : string ,
2021-02-20 00:35:50 +08:00
options : Options ,
2021-10-22 14:52:54 +08:00
storage : Storage ,
parent : ParentConfig < MarkConfig < Options , Storage > > [ 'extendMarkSchema' ] ,
2021-02-20 00:35:50 +08:00
} ,
2021-04-16 03:43:41 +08:00
extension : Mark ,
2021-04-21 15:43:31 +08:00
) = > Record < string , any > ) | null ,
2021-02-20 00:35:50 +08:00
2021-04-02 06:07:40 +08:00
/ * *
* The editor is not ready yet .
* /
2021-04-15 20:40:28 +08:00
onBeforeCreate ? : ( ( this : {
2021-04-21 05:11:35 +08:00
name : string ,
2021-04-02 06:07:40 +08:00
options : Options ,
2021-10-22 14:52:54 +08:00
storage : Storage ,
2021-04-02 06:07:40 +08:00
editor : Editor ,
type : MarkType ,
2021-10-22 14:52:54 +08:00
parent : ParentConfig < MarkConfig < Options , Storage > > [ 'onBeforeCreate' ] ,
2021-04-02 06:07:40 +08:00
} ) = > void ) | null ,
2021-02-20 00:35:50 +08:00
/ * *
* The editor is ready .
* /
onCreate ? : ( ( this : {
2021-04-21 05:11:35 +08:00
name : string ,
2021-02-20 00:35:50 +08:00
options : Options ,
2021-10-22 14:52:54 +08:00
storage : Storage ,
2021-02-20 00:35:50 +08:00
editor : Editor ,
type : MarkType ,
2021-10-22 14:52:54 +08:00
parent : ParentConfig < MarkConfig < Options , Storage > > [ 'onCreate' ] ,
2021-02-20 00:35:50 +08:00
} ) = > void ) | null ,
/ * *
* The content has changed .
* /
onUpdate ? : ( ( this : {
2021-04-21 05:11:35 +08:00
name : string ,
2021-02-20 00:35:50 +08:00
options : Options ,
2021-10-22 14:52:54 +08:00
storage : Storage ,
2021-02-20 00:35:50 +08:00
editor : Editor ,
type : MarkType ,
2021-10-22 14:52:54 +08:00
parent : ParentConfig < MarkConfig < Options , Storage > > [ 'onUpdate' ] ,
2021-02-20 00:35:50 +08:00
} ) = > void ) | null ,
/ * *
* The selection has changed .
* /
2021-04-02 00:42:31 +08:00
onSelectionUpdate ? : ( ( this : {
2021-04-21 05:11:35 +08:00
name : string ,
2021-03-09 16:50:03 +08:00
options : Options ,
2021-10-22 14:52:54 +08:00
storage : Storage ,
2021-03-09 16:50:03 +08:00
editor : Editor ,
type : MarkType ,
2021-10-22 14:52:54 +08:00
parent : ParentConfig < MarkConfig < Options , Storage > > [ 'onSelectionUpdate' ] ,
2021-03-09 16:50:03 +08:00
} ) = > void ) | null ,
2021-02-20 00:35:50 +08:00
/ * *
* The editor state has changed .
* /
onTransaction ? : ( (
this : {
2021-04-21 05:11:35 +08:00
name : string ,
2021-02-20 00:35:50 +08:00
options : Options ,
2021-10-22 14:52:54 +08:00
storage : Storage ,
2021-02-20 00:35:50 +08:00
editor : Editor ,
type : MarkType ,
2021-10-22 14:52:54 +08:00
parent : ParentConfig < MarkConfig < Options , Storage > > [ 'onTransaction' ] ,
2021-02-20 00:35:50 +08:00
} ,
props : {
transaction : Transaction ,
} ,
) = > void ) | null ,
/ * *
* The editor is focused .
* /
onFocus ? : ( (
this : {
2021-04-21 05:11:35 +08:00
name : string ,
2021-02-20 00:35:50 +08:00
options : Options ,
2021-10-22 14:52:54 +08:00
storage : Storage ,
2021-02-20 00:35:50 +08:00
editor : Editor ,
type : MarkType ,
2021-10-22 14:52:54 +08:00
parent : ParentConfig < MarkConfig < Options , Storage > > [ 'onFocus' ] ,
2021-02-20 00:35:50 +08:00
} ,
props : {
event : FocusEvent ,
} ,
) = > void ) | null ,
/ * *
* The editor isn ’ t focused anymore .
* /
onBlur ? : ( (
this : {
2021-04-21 05:11:35 +08:00
name : string ,
2021-02-20 00:35:50 +08:00
options : Options ,
2021-10-22 14:52:54 +08:00
storage : Storage ,
2021-02-20 00:35:50 +08:00
editor : Editor ,
type : MarkType ,
2021-10-22 14:52:54 +08:00
parent : ParentConfig < MarkConfig < Options , Storage > > [ 'onBlur' ] ,
2021-02-20 00:35:50 +08:00
} ,
props : {
event : FocusEvent ,
} ,
) = > void ) | null ,
/ * *
* The editor is destroyed .
* /
onDestroy ? : ( ( this : {
2021-04-21 05:11:35 +08:00
name : string ,
2021-02-20 00:35:50 +08:00
options : Options ,
2021-10-22 14:52:54 +08:00
storage : Storage ,
2021-02-20 00:35:50 +08:00
editor : Editor ,
type : MarkType ,
2021-10-22 14:52:54 +08:00
parent : ParentConfig < MarkConfig < Options , Storage > > [ 'onDestroy' ] ,
2021-02-20 00:35:50 +08:00
} ) = > void ) | null ,
2021-04-02 01:06:40 +08:00
/ * *
* Keep mark after split node
* /
keepOnSplit? : boolean | ( ( ) = > boolean ) ,
2021-02-20 00:35:50 +08:00
/ * *
* Inclusive
* /
2021-04-12 17:11:02 +08:00
inclusive? : MarkSpec [ 'inclusive' ] | ( ( this : {
2021-04-21 05:11:35 +08:00
name : string ,
2021-04-12 17:11:02 +08:00
options : Options ,
2021-10-22 14:52:54 +08:00
storage : Storage ,
parent : ParentConfig < MarkConfig < Options , Storage > > [ 'inclusive' ] ,
2021-04-12 17:11:02 +08:00
} ) = > MarkSpec [ 'inclusive' ] ) ,
2021-02-20 00:35:50 +08:00
/ * *
* Excludes
* /
2021-04-12 17:11:02 +08:00
excludes? : MarkSpec [ 'excludes' ] | ( ( this : {
2021-04-21 05:11:35 +08:00
name : string ,
2021-04-12 17:11:02 +08:00
options : Options ,
2021-10-22 14:52:54 +08:00
storage : Storage ,
parent : ParentConfig < MarkConfig < Options , Storage > > [ 'excludes' ] ,
2021-04-12 17:11:02 +08:00
} ) = > MarkSpec [ 'excludes' ] ) ,
2021-02-20 00:35:50 +08:00
/ * *
* Group
* /
2021-04-12 17:11:02 +08:00
group? : MarkSpec [ 'group' ] | ( ( this : {
2021-04-21 05:11:35 +08:00
name : string ,
2021-04-12 17:11:02 +08:00
options : Options ,
2021-10-22 14:52:54 +08:00
storage : Storage ,
parent : ParentConfig < MarkConfig < Options , Storage > > [ 'group' ] ,
2021-04-12 17:11:02 +08:00
} ) = > MarkSpec [ 'group' ] ) ,
2021-02-20 00:35:50 +08:00
/ * *
* Spanning
* /
2021-04-12 17:11:02 +08:00
spanning? : MarkSpec [ 'spanning' ] | ( ( this : {
2021-04-21 05:11:35 +08:00
name : string ,
2021-04-12 17:11:02 +08:00
options : Options ,
2021-10-22 14:52:54 +08:00
storage : Storage ,
parent : ParentConfig < MarkConfig < Options , Storage > > [ 'spanning' ] ,
2021-04-12 17:11:02 +08:00
} ) = > MarkSpec [ 'spanning' ] ) ,
2021-02-20 00:35:50 +08:00
/ * *
2021-10-08 21:02:09 +08:00
* Code
* /
code? : boolean | ( ( this : {
name : string ,
options : Options ,
2021-10-22 14:52:54 +08:00
storage : Storage ,
parent : ParentConfig < MarkConfig < Options , Storage > > [ 'code' ] ,
2021-10-08 21:02:09 +08:00
} ) = > boolean ) ,
/ * *
2021-02-20 00:35:50 +08:00
* Parse HTML
* /
parseHTML ? : (
this : {
2021-04-21 05:11:35 +08:00
name : string ,
2021-02-20 00:35:50 +08:00
options : Options ,
2021-10-22 14:52:54 +08:00
storage : Storage ,
parent : ParentConfig < MarkConfig < Options , Storage > > [ 'parseHTML' ] ,
2021-02-20 00:35:50 +08:00
} ,
) = > MarkSpec [ 'parseDOM' ] ,
/ * *
* Render HTML
* /
renderHTML ? : ( (
this : {
2021-04-21 05:11:35 +08:00
name : string ,
2021-02-20 00:35:50 +08:00
options : Options ,
2021-10-22 14:52:54 +08:00
storage : Storage ,
parent : ParentConfig < MarkConfig < Options , Storage > > [ 'renderHTML' ] ,
2021-02-20 00:35:50 +08:00
} ,
props : {
mark : ProseMirrorMark ,
2021-04-21 15:43:31 +08:00
HTMLAttributes : Record < string , any > ,
2021-04-15 20:40:28 +08:00
} ,
2021-02-20 00:35:50 +08:00
) = > DOMOutputSpec ) | null ,
/ * *
* Attributes
* /
addAttributes ? : (
this : {
2021-04-21 05:11:35 +08:00
name : string ,
2021-02-20 00:35:50 +08:00
options : Options ,
2021-10-22 14:52:54 +08:00
storage : Storage ,
parent : ParentConfig < MarkConfig < Options , Storage > > [ 'addAttributes' ] ,
2021-02-20 00:35:50 +08:00
} ,
) = > Attributes | { } ,
}
}
2020-10-22 03:13:38 +08:00
2021-10-22 14:52:54 +08:00
export class Mark < Options = any , Storage = any > {
2021-04-16 04:03:45 +08:00
type = 'mark'
2020-11-20 04:08:25 +08:00
2021-04-16 04:03:45 +08:00
name = 'mark'
2021-04-15 20:40:28 +08:00
parent : Mark | null = null
2021-04-12 17:11:02 +08:00
2021-04-15 20:40:28 +08:00
child : Mark | null = null
2020-11-16 06:25:25 +08:00
2021-04-16 04:03:45 +08:00
options : Options
2021-10-22 14:52:54 +08:00
storage : Storage
2021-04-16 04:03:45 +08:00
config : MarkConfig = {
name : this.name ,
defaultOptions : { } ,
}
2021-10-22 14:52:54 +08:00
constructor ( config : Partial < MarkConfig < Options , Storage > > = { } ) {
2020-11-16 06:25:25 +08:00
this . config = {
. . . this . config ,
2020-10-22 03:13:38 +08:00
. . . config ,
2020-11-16 06:25:25 +08:00
}
2021-04-16 04:03:45 +08:00
this . name = this . config . name
2021-10-27 00:31:13 +08:00
if ( config . defaultOptions ) {
console . warn ( ` [tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: " ${ this . name } ". ` )
}
// TODO: remove `addOptions` fallback
2020-11-16 06:25:25 +08:00
this . options = this . config . defaultOptions
2021-10-27 00:31:13 +08:00
if ( this . config . addOptions ) {
this . options = callOrReturn ( getExtensionField < AnyConfig [ ' addOptions ' ] > (
this ,
'addOptions' ,
{
name : this.name ,
} ,
) )
}
2021-10-22 14:52:54 +08:00
this . storage = callOrReturn ( getExtensionField < AnyConfig [ ' addStorage ' ] > (
this ,
'addStorage' ,
{
name : this.name ,
options : this.options ,
} ,
2021-10-27 00:31:13 +08:00
) ) || { }
2020-10-22 03:13:38 +08:00
}
2021-10-22 14:52:54 +08:00
static create < O = any , S = any > ( config : Partial < MarkConfig < O , S > > = { } ) {
return new Mark < O , S > ( config )
2020-11-16 06:25:25 +08:00
}
2020-10-22 03:13:38 +08:00
2021-01-20 05:29:46 +08:00
configure ( options : Partial < Options > = { } ) {
2021-05-11 23:03:34 +08:00
// return a new instance so we can use the same extension
// with different calls of `configure`
2021-06-03 19:13:43 +08:00
const extension = this . extend ( )
extension . options = mergeDeep ( this . options , options ) as Options
2021-10-25 06:27:24 +08:00
extension . storage = callOrReturn ( getExtensionField < AnyConfig [ ' addStorage ' ] > (
extension ,
'addStorage' ,
{
name : extension.name ,
options : extension.options ,
} ,
) )
2021-06-03 19:13:43 +08:00
return extension
2020-10-22 03:13:38 +08:00
}
2021-10-22 14:52:54 +08:00
extend < ExtendedOptions = Options , ExtendedStorage = Storage > ( extendedConfig : Partial < MarkConfig < ExtendedOptions , ExtendedStorage > > = { } ) {
const extension = new Mark < ExtendedOptions , ExtendedStorage > ( extendedConfig )
2021-04-12 17:11:02 +08:00
2021-04-14 15:48:38 +08:00
extension . parent = this
2021-04-15 20:40:28 +08:00
this . child = extension
2021-04-16 04:03:45 +08:00
extension . name = extendedConfig . name
? extendedConfig . name
2021-04-18 03:25:29 +08:00
: extension . parent . name
2021-04-16 04:03:45 +08:00
2021-10-27 00:31:13 +08:00
if ( extendedConfig . defaultOptions ) {
console . warn ( ` [tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: " ${ extension . name } ". ` )
}
2021-12-03 03:04:45 +08:00
extension . options = callOrReturn ( getExtensionField < AnyConfig [ ' addOptions ' ] > (
extension ,
'addOptions' ,
{
name : extension.name ,
} ,
) )
2021-10-27 00:31:13 +08:00
2021-10-22 14:52:54 +08:00
extension . storage = callOrReturn ( getExtensionField < AnyConfig [ ' addStorage ' ] > (
extension ,
'addStorage' ,
{
name : extension.name ,
options : extension.options ,
} ,
) )
2021-04-12 17:11:02 +08:00
return extension
2020-11-16 06:25:25 +08:00
}
2020-10-22 03:13:38 +08:00
}