2020-11-30 21:12:36 +08:00
import { Plugin , Transaction } from 'prosemirror-state'
2021-10-08 21:02:09 +08:00
import { InputRule } from './InputRule'
import { PasteRule } from './PasteRule'
2020-10-22 15:14:24 +08:00
import { Editor } from './Editor'
2021-02-19 16:54:39 +08:00
import { Node } from './Node'
2021-04-16 03:43:41 +08:00
import { Mark } from './Mark'
2021-12-06 19:00:09 +08:00
import { mergeDeep } from './utilities/mergeDeep'
import { callOrReturn } from './utilities/callOrReturn'
import { getExtensionField } from './helpers/getExtensionField'
2021-04-21 04:58:09 +08:00
import {
2021-10-22 14:52:54 +08:00
AnyConfig ,
2021-05-07 16:08:30 +08:00
Extensions ,
2021-04-21 04:58:09 +08:00
GlobalAttributes ,
RawCommands ,
ParentConfig ,
KeyboardShortcutCommand ,
} from './types'
2021-03-31 19:44:56 +08:00
import { ExtensionConfig } from '.'
2021-02-20 00:35:50 +08:00
declare module '@tiptap/core' {
2021-10-22 14:52:54 +08:00
interface ExtensionConfig < 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 < ExtensionConfig < Options , Storage > > [ 'addOptions' ] , undefined > ,
} ) = > Options ,
2021-10-22 14:52:54 +08:00
/ * *
* Default Storage
* /
addStorage ? : ( this : {
name : string ,
options : Options ,
2021-10-27 00:31:13 +08:00
parent : Exclude < ParentConfig < ExtensionConfig < 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 ,
2021-02-19 16:54:39 +08:00
options : Options ,
2021-10-22 14:52:54 +08:00
storage : Storage ,
parent : ParentConfig < ExtensionConfig < Options , Storage > > [ 'addGlobalAttributes' ] ,
2021-02-20 00:35:50 +08:00
} ) = > GlobalAttributes | { } ,
/ * *
* Raw
* /
addCommands ? : ( this : {
2021-04-21 05:11:35 +08:00
name : string ,
2021-02-19 16:54:39 +08:00
options : Options ,
2021-10-22 14:52:54 +08:00
storage : Storage ,
2021-02-20 00:35:50 +08:00
editor : Editor ,
2021-10-22 14:52:54 +08:00
parent : ParentConfig < ExtensionConfig < Options , Storage > > [ 'addCommands' ] ,
2021-02-20 00:35:50 +08:00
} ) = > Partial < RawCommands > ,
/ * *
* Keyboard shortcuts
* /
addKeyboardShortcuts ? : ( 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 ,
2021-10-22 14:52:54 +08:00
parent : ParentConfig < ExtensionConfig < Options , Storage > > [ 'addKeyboardShortcuts' ] ,
2021-02-20 00:35:50 +08:00
} ) = > {
2021-04-21 04:58:09 +08:00
[ key : string ] : KeyboardShortcutCommand ,
2020-11-30 21:12:36 +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 ,
2021-10-22 14:52:54 +08:00
parent : ParentConfig < ExtensionConfig < 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 ,
2021-10-22 14:52:54 +08:00
parent : ParentConfig < ExtensionConfig < Options , Storage > > [ 'addPasteRules' ] ,
2021-10-08 21:02:09 +08:00
} ) = > PasteRule [ ] ,
2021-02-20 00:35:50 +08:00
/ * *
* ProseMirror plugins
* /
addProseMirrorPlugins ? : ( 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 ,
2021-10-22 14:52:54 +08:00
parent : ParentConfig < ExtensionConfig < 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 < ExtensionConfig < 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 < ExtensionConfig < 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 < ExtensionConfig < 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-21 05:11:35 +08:00
onBeforeCreate ? : ( ( this : {
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 ,
2021-10-22 14:52:54 +08:00
parent : ParentConfig < ExtensionConfig < 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 ,
2021-10-22 14:52:54 +08:00
parent : ParentConfig < ExtensionConfig < 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 ,
2021-10-22 14:52:54 +08:00
parent : ParentConfig < ExtensionConfig < Options , Storage > > [ 'onUpdate' ] ,
2021-02-20 00:35:50 +08:00
} ) = > void ) | null ,
/ * *
* The selection has changed .
* /
2021-03-09 16:50:03 +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 ,
2021-10-22 14:52:54 +08:00
parent : ParentConfig < ExtensionConfig < 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 ,
2021-10-22 14:52:54 +08:00
parent : ParentConfig < ExtensionConfig < 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 ,
2021-10-22 14:52:54 +08:00
parent : ParentConfig < ExtensionConfig < 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 ,
2021-10-22 14:52:54 +08:00
parent : ParentConfig < ExtensionConfig < 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 ,
2021-10-22 14:52:54 +08:00
parent : ParentConfig < ExtensionConfig < Options , Storage > > [ 'onDestroy' ] ,
2021-02-20 00:35:50 +08:00
} ) = > void ) | null ,
}
2020-10-21 21:17:05 +08:00
}
2020-09-24 06:29:05 +08:00
2021-10-22 14:52:54 +08:00
export class Extension < Options = any , Storage = any > {
2020-11-20 04:08:25 +08:00
type = 'extension'
2021-04-16 04:03:45 +08:00
name = 'extension'
2021-04-12 17:11:02 +08:00
2021-04-15 20:40:28 +08:00
parent : Extension | null = null
2020-11-16 06:25:25 +08:00
2021-04-15 20:40:28 +08:00
child : Extension | null = null
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 : ExtensionConfig = {
name : this.name ,
defaultOptions : { } ,
}
2021-10-22 14:52:54 +08:00
constructor ( config : Partial < ExtensionConfig < Options , Storage > > = { } ) {
2020-11-16 06:25:25 +08:00
this . config = {
. . . this . config ,
2020-10-21 21:17:05 +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-09-09 05:44:45 +08:00
}
2021-10-22 14:52:54 +08:00
static create < O = any , S = any > ( config : Partial < ExtensionConfig < O , S > > = { } ) {
return new Extension < O , S > ( config )
2020-11-16 06:25:25 +08:00
}
2020-04-13 20:03:39 +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
2019-12-17 06:20:05 +08:00
}
2021-10-22 14:52:54 +08:00
extend < ExtendedOptions = Options , ExtendedStorage = Storage > ( extendedConfig : Partial < ExtensionConfig < ExtendedOptions , ExtendedStorage > > = { } ) {
const extension = new Extension < 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
}
2019-12-17 06:20:05 +08:00
}