@tiptap/core 3.0.0-next.4 → 3.0.0-next.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/LICENSE.md +1 -1
  2. package/dist/index.cjs +352 -238
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +1084 -1431
  5. package/dist/index.d.ts +1084 -1431
  6. package/dist/index.js +344 -235
  7. package/dist/index.js.map +1 -1
  8. package/dist/jsx-runtime/jsx-runtime.cjs +56 -0
  9. package/dist/jsx-runtime/jsx-runtime.cjs.map +1 -0
  10. package/dist/jsx-runtime/jsx-runtime.d.cts +22 -0
  11. package/dist/jsx-runtime/jsx-runtime.d.ts +22 -0
  12. package/dist/jsx-runtime/jsx-runtime.js +26 -0
  13. package/dist/jsx-runtime/jsx-runtime.js.map +1 -0
  14. package/jsx-runtime/index.cjs +1 -0
  15. package/jsx-runtime/index.d.cts +1 -0
  16. package/jsx-runtime/index.d.ts +1 -0
  17. package/jsx-runtime/index.js +1 -0
  18. package/package.json +20 -3
  19. package/src/Editor.ts +104 -22
  20. package/src/Extendable.ts +483 -0
  21. package/src/Extension.ts +5 -490
  22. package/src/ExtensionManager.ts +55 -10
  23. package/src/Mark.ts +135 -623
  24. package/src/MarkView.ts +66 -0
  25. package/src/Node.ts +325 -829
  26. package/src/commands/clearContent.ts +9 -4
  27. package/src/commands/focus.ts +7 -1
  28. package/src/commands/insertContentAt.ts +6 -2
  29. package/src/commands/setContent.ts +15 -14
  30. package/src/extensions/delete.ts +89 -0
  31. package/src/extensions/index.ts +1 -0
  32. package/src/extensions/keymap.ts +4 -0
  33. package/src/helpers/getExtensionField.ts +10 -7
  34. package/src/index.ts +3 -7
  35. package/src/jsx-runtime.ts +64 -0
  36. package/src/types.ts +334 -19
  37. package/src/utilities/elementFromString.ts +3 -0
  38. package/src/utilities/index.ts +1 -0
  39. package/src/utilities/mergeAttributes.ts +1 -1
package/src/Mark.ts CHANGED
@@ -1,643 +1,155 @@
1
- import { DOMOutputSpec, Mark as ProseMirrorMark, MarkSpec, MarkType } from '@tiptap/pm/model'
2
- import { Plugin, Transaction } from '@tiptap/pm/state'
3
-
4
- import { Editor } from './Editor.js'
5
- import { getExtensionField } from './helpers/getExtensionField.js'
6
- import { MarkConfig } from './index.js'
7
- import { InputRule } from './InputRule.js'
8
- import { Node } from './Node.js'
9
- import { PasteRule } from './PasteRule.js'
10
- import {
11
- AnyConfig,
12
- Attributes,
13
- Extensions,
14
- GlobalAttributes,
15
- KeyboardShortcutCommand,
16
- ParentConfig,
17
- RawCommands,
18
- } from './types.js'
19
- import { callOrReturn } from './utilities/callOrReturn.js'
20
- import { mergeDeep } from './utilities/mergeDeep.js'
21
-
22
- declare module '@tiptap/core' {
23
- export interface MarkConfig<Options = any, Storage = any> {
24
- // @ts-ignore - this is a dynamic key
25
- [key: string]: any
26
-
27
- /**
28
- * The extension name - this must be unique.
29
- * It will be used to identify the extension.
30
- *
31
- * @example 'myExtension'
32
- */
1
+ import type { DOMOutputSpec, Mark as ProseMirrorMark, MarkSpec, MarkType } from '@tiptap/pm/model'
2
+
3
+ import type { Editor } from './Editor.js'
4
+ import type { ExtendableConfig } from './Extendable.js'
5
+ import { Extendable } from './Extendable.js'
6
+ import type { Attributes, MarkViewRenderer, ParentConfig } from './types.js'
7
+
8
+ export interface MarkConfig<Options = any, Storage = any>
9
+ extends ExtendableConfig<Options, Storage, MarkConfig<Options, Storage>, MarkType> {
10
+ /**
11
+ * Mark View
12
+ */
13
+ addMarkView?:
14
+ | ((this: {
15
+ name: string
16
+ options: Options
17
+ storage: Storage
18
+ editor: Editor
19
+ type: MarkType
20
+ parent: ParentConfig<MarkConfig<Options, Storage>>['addMarkView']
21
+ }) => MarkViewRenderer)
22
+ | null
23
+
24
+ /**
25
+ * Keep mark after split node
26
+ */
27
+ keepOnSplit?: boolean | (() => boolean)
28
+
29
+ /**
30
+ * Inclusive
31
+ */
32
+ inclusive?:
33
+ | MarkSpec['inclusive']
34
+ | ((this: {
35
+ name: string
36
+ options: Options
37
+ storage: Storage
38
+ parent: ParentConfig<MarkConfig<Options, Storage>>['inclusive']
39
+ editor?: Editor
40
+ }) => MarkSpec['inclusive'])
41
+
42
+ /**
43
+ * Excludes
44
+ */
45
+ excludes?:
46
+ | MarkSpec['excludes']
47
+ | ((this: {
48
+ name: string
49
+ options: Options
50
+ storage: Storage
51
+ parent: ParentConfig<MarkConfig<Options, Storage>>['excludes']
52
+ editor?: Editor
53
+ }) => MarkSpec['excludes'])
54
+
55
+ /**
56
+ * Marks this Mark as exitable
57
+ */
58
+ exitable?: boolean | (() => boolean)
59
+
60
+ /**
61
+ * Group
62
+ */
63
+ group?:
64
+ | MarkSpec['group']
65
+ | ((this: {
66
+ name: string
67
+ options: Options
68
+ storage: Storage
69
+ parent: ParentConfig<MarkConfig<Options, Storage>>['group']
70
+ editor?: Editor
71
+ }) => MarkSpec['group'])
72
+
73
+ /**
74
+ * Spanning
75
+ */
76
+ spanning?:
77
+ | MarkSpec['spanning']
78
+ | ((this: {
79
+ name: string
80
+ options: Options
81
+ storage: Storage
82
+ parent: ParentConfig<MarkConfig<Options, Storage>>['spanning']
83
+ editor?: Editor
84
+ }) => MarkSpec['spanning'])
85
+
86
+ /**
87
+ * Code
88
+ */
89
+ code?:
90
+ | boolean
91
+ | ((this: {
92
+ name: string
93
+ options: Options
94
+ storage: Storage
95
+ parent: ParentConfig<MarkConfig<Options, Storage>>['code']
96
+ editor?: Editor
97
+ }) => boolean)
98
+
99
+ /**
100
+ * Parse HTML
101
+ */
102
+ parseHTML?: (this: {
33
103
  name: string
34
-
35
- /**
36
- * The priority of your extension. The higher, the earlier it will be called
37
- * and will take precedence over other extensions with a lower priority.
38
- * @default 100
39
- * @example 101
40
- */
41
- priority?: number
42
-
43
- /**
44
- * The default options for this extension.
45
- * @example
46
- * defaultOptions: {
47
- * myOption: 'foo',
48
- * myOtherOption: 10,
49
- * }
50
- */
51
- defaultOptions?: Options
52
-
53
- /**
54
- * This method will add options to this extension
55
- * @see https://tiptap.dev/guide/custom-extensions#settings
56
- * @example
57
- * addOptions() {
58
- * return {
59
- * myOption: 'foo',
60
- * myOtherOption: 10,
61
- * }
62
- */
63
- addOptions?: (this: {
64
- name: string
65
- parent: Exclude<ParentConfig<MarkConfig<Options, Storage>>['addOptions'], undefined>
66
- }) => Options
67
-
68
- /**
69
- * The default storage this extension can save data to.
70
- * @see https://tiptap.dev/guide/custom-extensions#storage
71
- * @example
72
- * defaultStorage: {
73
- * prefetchedUsers: [],
74
- * loading: false,
75
- * }
76
- */
77
- addStorage?: (this: {
78
- name: string
79
- options: Options
80
- parent: Exclude<ParentConfig<MarkConfig<Options, Storage>>['addStorage'], undefined>
81
- }) => Storage
82
-
83
- /**
84
- * This function adds globalAttributes to specific nodes.
85
- * @see https://tiptap.dev/guide/custom-extensions#global-attributes
86
- * @example
87
- * addGlobalAttributes() {
88
- * return [
89
- * {
90
- // Extend the following extensions
91
- * types: [
92
- * 'heading',
93
- * 'paragraph',
94
- * ],
95
- * // … with those attributes
96
- * attributes: {
97
- * textAlign: {
98
- * default: 'left',
99
- * renderHTML: attributes => ({
100
- * style: `text-align: ${attributes.textAlign}`,
101
- * }),
102
- * parseHTML: element => element.style.textAlign || 'left',
103
- * },
104
- * },
105
- * },
106
- * ]
107
- * }
108
- */
109
- addGlobalAttributes?: (this: {
110
- name: string
111
- options: Options
112
- storage: Storage
113
- extensions: (Node | Mark)[]
114
- parent: ParentConfig<MarkConfig<Options, Storage>>['addGlobalAttributes']
115
- }) => GlobalAttributes
116
-
117
- /**
118
- * This function adds commands to the editor
119
- * @see https://tiptap.dev/guide/custom-extensions#keyboard-shortcuts
120
- * @example
121
- * addCommands() {
122
- * return {
123
- * myCommand: () => ({ chain }) => chain().setMark('type', 'foo').run(),
124
- * }
125
- * }
126
- */
127
- addCommands?: (this: {
128
- name: string
129
- options: Options
130
- storage: Storage
131
- editor: Editor
132
- type: MarkType
133
- parent: ParentConfig<MarkConfig<Options, Storage>>['addCommands']
134
- }) => Partial<RawCommands>
135
-
136
- /**
137
- * This function registers keyboard shortcuts.
138
- * @see https://tiptap.dev/guide/custom-extensions#keyboard-shortcuts
139
- * @example
140
- * addKeyboardShortcuts() {
141
- * return {
142
- * 'Mod-l': () => this.editor.commands.toggleBulletList(),
143
- * }
144
- * },
145
- */
146
- addKeyboardShortcuts?: (this: {
147
- name: string
148
- options: Options
149
- storage: Storage
150
- editor: Editor
151
- type: MarkType
152
- parent: ParentConfig<MarkConfig<Options, Storage>>['addKeyboardShortcuts']
153
- }) => {
154
- [key: string]: KeyboardShortcutCommand
155
- }
156
-
157
- /**
158
- * This function adds input rules to the editor.
159
- * @see https://tiptap.dev/guide/custom-extensions#input-rules
160
- * @example
161
- * addInputRules() {
162
- * return [
163
- * markInputRule({
164
- * find: inputRegex,
165
- * type: this.type,
166
- * }),
167
- * ]
168
- * },
169
- */
170
- addInputRules?: (this: {
171
- name: string
172
- options: Options
173
- storage: Storage
174
- editor: Editor
175
- type: MarkType
176
- parent: ParentConfig<MarkConfig<Options, Storage>>['addInputRules']
177
- }) => InputRule[]
178
-
179
- /**
180
- * This function adds paste rules to the editor.
181
- * @see https://tiptap.dev/guide/custom-extensions#paste-rules
182
- * @example
183
- * addPasteRules() {
184
- * return [
185
- * markPasteRule({
186
- * find: pasteRegex,
187
- * type: this.type,
188
- * }),
189
- * ]
190
- * },
191
- */
192
- addPasteRules?: (this: {
193
- name: string
194
- options: Options
195
- storage: Storage
196
- editor: Editor
197
- type: MarkType
198
- parent: ParentConfig<MarkConfig<Options, Storage>>['addPasteRules']
199
- }) => PasteRule[]
200
-
201
- /**
202
- * This function adds Prosemirror plugins to the editor
203
- * @see https://tiptap.dev/guide/custom-extensions#prosemirror-plugins
204
- * @example
205
- * addProseMirrorPlugins() {
206
- * return [
207
- * customPlugin(),
208
- * ]
209
- * }
210
- */
211
- addProseMirrorPlugins?: (this: {
212
- name: string
213
- options: Options
214
- storage: Storage
215
- editor: Editor
216
- type: MarkType
217
- parent: ParentConfig<MarkConfig<Options, Storage>>['addProseMirrorPlugins']
218
- }) => Plugin[]
219
-
220
- /**
221
- * This function adds additional extensions to the editor. This is useful for
222
- * building extension kits.
223
- * @example
224
- * addExtensions() {
225
- * return [
226
- * BulletList,
227
- * OrderedList,
228
- * ListItem
229
- * ]
230
- * }
231
- */
232
- addExtensions?: (this: {
233
- name: string
234
- options: Options
235
- storage: Storage
236
- parent: ParentConfig<MarkConfig<Options, Storage>>['addExtensions']
237
- }) => Extensions
238
-
239
- /**
240
- * This function extends the schema of the node.
241
- * @example
242
- * extendNodeSchema() {
243
- * return {
244
- * group: 'inline',
245
- * selectable: false,
246
- * }
247
- * }
248
- */
249
- extendNodeSchema?:
250
- | ((
251
- this: {
252
- name: string
253
- options: Options
254
- storage: Storage
255
- parent: ParentConfig<MarkConfig<Options, Storage>>['extendNodeSchema']
256
- },
257
- extension: Node,
258
- ) => Record<string, any>)
259
- | null
260
-
261
- /**
262
- * This function extends the schema of the mark.
263
- * @example
264
- * extendMarkSchema() {
265
- * return {
266
- * group: 'inline',
267
- * selectable: false,
268
- * }
269
- * }
270
- */
271
- extendMarkSchema?:
272
- | ((
273
- this: {
274
- name: string
275
- options: Options
276
- storage: Storage
277
- parent: ParentConfig<MarkConfig<Options, Storage>>['extendMarkSchema']
278
- },
279
- extension: Mark,
280
- ) => Record<string, any>)
281
- | null
282
-
283
- /**
284
- * The editor is not ready yet.
285
- */
286
- onBeforeCreate?:
287
- | ((this: {
288
- name: string
289
- options: Options
290
- storage: Storage
291
- editor: Editor
292
- type: MarkType
293
- parent: ParentConfig<MarkConfig<Options, Storage>>['onBeforeCreate']
294
- }) => void)
295
- | null
296
-
297
- /**
298
- * The editor is ready.
299
- */
300
- onCreate?:
301
- | ((this: {
302
- name: string
303
- options: Options
304
- storage: Storage
305
- editor: Editor
306
- type: MarkType
307
- parent: ParentConfig<MarkConfig<Options, Storage>>['onCreate']
308
- }) => void)
309
- | null
310
-
311
- /**
312
- * The content has changed.
313
- */
314
- onUpdate?:
315
- | ((this: {
104
+ options: Options
105
+ storage: Storage
106
+ parent: ParentConfig<MarkConfig<Options, Storage>>['parseHTML']
107
+ editor?: Editor
108
+ }) => MarkSpec['parseDOM']
109
+
110
+ /**
111
+ * Render HTML
112
+ */
113
+ renderHTML?:
114
+ | ((
115
+ this: {
316
116
  name: string
317
117
  options: Options
318
118
  storage: Storage
319
- editor: Editor
320
- type: MarkType
321
- parent: ParentConfig<MarkConfig<Options, Storage>>['onUpdate']
322
- }) => void)
323
- | null
324
-
325
- /**
326
- * The selection has changed.
327
- */
328
- onSelectionUpdate?:
329
- | ((this: {
330
- name: string
331
- options: Options
332
- storage: Storage
333
- editor: Editor
334
- type: MarkType
335
- parent: ParentConfig<MarkConfig<Options, Storage>>['onSelectionUpdate']
336
- }) => void)
337
- | null
338
-
339
- /**
340
- * The editor state has changed.
341
- */
342
- onTransaction?:
343
- | ((
344
- this: {
345
- name: string
346
- options: Options
347
- storage: Storage
348
- editor: Editor
349
- type: MarkType
350
- parent: ParentConfig<MarkConfig<Options, Storage>>['onTransaction']
351
- },
352
- props: {
353
- editor: Editor
354
- transaction: Transaction
355
- },
356
- ) => void)
357
- | null
358
-
359
- /**
360
- * The editor is focused.
361
- */
362
- onFocus?:
363
- | ((
364
- this: {
365
- name: string
366
- options: Options
367
- storage: Storage
368
- editor: Editor
369
- type: MarkType
370
- parent: ParentConfig<MarkConfig<Options, Storage>>['onFocus']
371
- },
372
- props: {
373
- event: FocusEvent
374
- },
375
- ) => void)
376
- | null
377
-
378
- /**
379
- * The editor isn’t focused anymore.
380
- */
381
- onBlur?:
382
- | ((
383
- this: {
384
- name: string
385
- options: Options
386
- storage: Storage
387
- editor: Editor
388
- type: MarkType
389
- parent: ParentConfig<MarkConfig<Options, Storage>>['onBlur']
390
- },
391
- props: {
392
- event: FocusEvent
393
- },
394
- ) => void)
395
- | null
396
-
397
- /**
398
- * The editor is destroyed.
399
- */
400
- onDestroy?:
401
- | ((this: {
402
- name: string
403
- options: Options
404
- storage: Storage
405
- editor: Editor
406
- type: MarkType
407
- parent: ParentConfig<MarkConfig<Options, Storage>>['onDestroy']
408
- }) => void)
409
- | null
410
-
411
- /**
412
- * Keep mark after split node
413
- */
414
- keepOnSplit?: boolean | (() => boolean)
415
-
416
- /**
417
- * Inclusive
418
- */
419
- inclusive?:
420
- | MarkSpec['inclusive']
421
- | ((this: {
422
- name: string
423
- options: Options
424
- storage: Storage
425
- parent: ParentConfig<MarkConfig<Options, Storage>>['inclusive']
426
- editor?: Editor
427
- }) => MarkSpec['inclusive'])
428
-
429
- /**
430
- * Excludes
431
- */
432
- excludes?:
433
- | MarkSpec['excludes']
434
- | ((this: {
435
- name: string
436
- options: Options
437
- storage: Storage
438
- parent: ParentConfig<MarkConfig<Options, Storage>>['excludes']
119
+ parent: ParentConfig<MarkConfig<Options, Storage>>['renderHTML']
439
120
  editor?: Editor
440
- }) => MarkSpec['excludes'])
441
-
442
- /**
443
- * Marks this Mark as exitable
444
- */
445
- exitable?: boolean | (() => boolean)
446
-
447
- /**
448
- * Group
449
- */
450
- group?:
451
- | MarkSpec['group']
452
- | ((this: {
453
- name: string
454
- options: Options
455
- storage: Storage
456
- parent: ParentConfig<MarkConfig<Options, Storage>>['group']
457
- editor?: Editor
458
- }) => MarkSpec['group'])
459
-
460
- /**
461
- * Spanning
462
- */
463
- spanning?:
464
- | MarkSpec['spanning']
465
- | ((this: {
466
- name: string
467
- options: Options
468
- storage: Storage
469
- parent: ParentConfig<MarkConfig<Options, Storage>>['spanning']
470
- editor?: Editor
471
- }) => MarkSpec['spanning'])
472
-
473
- /**
474
- * Code
475
- */
476
- code?:
477
- | boolean
478
- | ((this: {
479
- name: string
480
- options: Options
481
- storage: Storage
482
- parent: ParentConfig<MarkConfig<Options, Storage>>['code']
483
- editor?: Editor
484
- }) => boolean)
485
-
486
- /**
487
- * Parse HTML
488
- */
489
- parseHTML?: (this: {
490
- name: string
491
- options: Options
492
- storage: Storage
493
- parent: ParentConfig<MarkConfig<Options, Storage>>['parseHTML']
494
- editor?: Editor
495
- }) => MarkSpec['parseDOM']
496
-
497
- /**
498
- * Render HTML
499
- */
500
- renderHTML?:
501
- | ((
502
- this: {
503
- name: string
504
- options: Options
505
- storage: Storage
506
- parent: ParentConfig<MarkConfig<Options, Storage>>['renderHTML']
507
- editor?: Editor
508
- },
509
- props: {
510
- mark: ProseMirrorMark
511
- HTMLAttributes: Record<string, any>
512
- },
513
- ) => DOMOutputSpec)
514
- | null
515
-
516
- /**
517
- * Attributes
518
- */
519
- addAttributes?: (this: {
520
- name: string
521
- options: Options
522
- storage: Storage
523
- parent: ParentConfig<MarkConfig<Options, Storage>>['addAttributes']
524
- editor?: Editor
525
- // eslint-disable-next-line @typescript-eslint/no-empty-object-type
526
- }) => Attributes | {}
527
- }
121
+ },
122
+ props: {
123
+ mark: ProseMirrorMark
124
+ HTMLAttributes: Record<string, any>
125
+ },
126
+ ) => DOMOutputSpec)
127
+ | null
128
+
129
+ /**
130
+ * Attributes
131
+ */
132
+ addAttributes?: (this: {
133
+ name: string
134
+ options: Options
135
+ storage: Storage
136
+ parent: ParentConfig<MarkConfig<Options, Storage>>['addAttributes']
137
+ editor?: Editor
138
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
139
+ }) => Attributes | {}
528
140
  }
529
141
 
530
142
  /**
531
143
  * The Mark class is used to create custom mark extensions.
532
144
  * @see https://tiptap.dev/api/extensions#create-a-new-extension
533
145
  */
534
- export class Mark<Options = any, Storage = any> {
146
+ export class Mark<Options = any, Storage = any> extends Extendable<Options, Storage> {
535
147
  type = 'mark'
536
148
 
537
- name = 'mark'
538
-
539
- parent: Mark | null = null
540
-
541
- child: Mark | null = null
542
-
543
- options: Options
544
-
545
- storage: Storage
546
-
547
- config: MarkConfig = {
548
- name: this.name,
549
- defaultOptions: {},
550
- }
551
-
552
- constructor(config: Partial<MarkConfig<Options, Storage>> = {}) {
553
- this.config = {
554
- ...this.config,
555
- ...config,
556
- }
557
-
558
- this.name = this.config.name
559
-
560
- if (config.defaultOptions && Object.keys(config.defaultOptions).length > 0) {
561
- console.warn(
562
- `[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${this.name}".`,
563
- )
564
- }
565
-
566
- // TODO: remove `addOptions` fallback
567
- this.options = this.config.defaultOptions
568
-
569
- if (this.config.addOptions) {
570
- this.options = callOrReturn(
571
- getExtensionField<AnyConfig['addOptions']>(this, 'addOptions', {
572
- name: this.name,
573
- }),
574
- )
575
- }
576
-
577
- this.storage =
578
- callOrReturn(
579
- getExtensionField<AnyConfig['addStorage']>(this, 'addStorage', {
580
- name: this.name,
581
- options: this.options,
582
- }),
583
- ) || {}
584
- }
585
-
586
149
  static create<O = any, S = any>(config: Partial<MarkConfig<O, S>> = {}) {
587
150
  return new Mark<O, S>(config)
588
151
  }
589
152
 
590
- configure(options: Partial<Options> = {}) {
591
- // return a new instance so we can use the same extension
592
- // with different calls of `configure`
593
- const extension = this.extend<Options, Storage>({
594
- ...this.config,
595
- addOptions: () => {
596
- return mergeDeep(this.options as Record<string, any>, options) as Options
597
- },
598
- })
599
-
600
- // Always preserve the current name
601
- extension.name = this.name
602
- // Set the parent to be our parent
603
- extension.parent = this.parent
604
-
605
- return extension
606
- }
607
-
608
- extend<ExtendedOptions = Options, ExtendedStorage = Storage>(
609
- extendedConfig: Partial<MarkConfig<ExtendedOptions, ExtendedStorage>> = {},
610
- ) {
611
- const extension = new Mark<ExtendedOptions, ExtendedStorage>(extendedConfig)
612
-
613
- extension.parent = this
614
-
615
- this.child = extension
616
-
617
- extension.name = extendedConfig.name ? extendedConfig.name : extension.parent.name
618
-
619
- if (extendedConfig.defaultOptions && Object.keys(extendedConfig.defaultOptions).length > 0) {
620
- console.warn(
621
- `[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${extension.name}".`,
622
- )
623
- }
624
-
625
- extension.options = callOrReturn(
626
- getExtensionField<AnyConfig['addOptions']>(extension, 'addOptions', {
627
- name: extension.name,
628
- }),
629
- )
630
-
631
- extension.storage = callOrReturn(
632
- getExtensionField<AnyConfig['addStorage']>(extension, 'addStorage', {
633
- name: extension.name,
634
- options: extension.options,
635
- }),
636
- )
637
-
638
- return extension
639
- }
640
-
641
153
  static handleExit({ editor, mark }: { editor: Editor; mark: Mark }) {
642
154
  const { tr } = editor.state
643
155
  const currentPos = editor.state.selection.$from