@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.
- package/LICENSE.md +1 -1
- package/dist/index.cjs +352 -238
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1084 -1431
- package/dist/index.d.ts +1084 -1431
- package/dist/index.js +344 -235
- package/dist/index.js.map +1 -1
- package/dist/jsx-runtime/jsx-runtime.cjs +56 -0
- package/dist/jsx-runtime/jsx-runtime.cjs.map +1 -0
- package/dist/jsx-runtime/jsx-runtime.d.cts +22 -0
- package/dist/jsx-runtime/jsx-runtime.d.ts +22 -0
- package/dist/jsx-runtime/jsx-runtime.js +26 -0
- package/dist/jsx-runtime/jsx-runtime.js.map +1 -0
- package/jsx-runtime/index.cjs +1 -0
- package/jsx-runtime/index.d.cts +1 -0
- package/jsx-runtime/index.d.ts +1 -0
- package/jsx-runtime/index.js +1 -0
- package/package.json +20 -3
- package/src/Editor.ts +104 -22
- package/src/Extendable.ts +483 -0
- package/src/Extension.ts +5 -490
- package/src/ExtensionManager.ts +55 -10
- package/src/Mark.ts +135 -623
- package/src/MarkView.ts +66 -0
- package/src/Node.ts +325 -829
- package/src/commands/clearContent.ts +9 -4
- package/src/commands/focus.ts +7 -1
- package/src/commands/insertContentAt.ts +6 -2
- package/src/commands/setContent.ts +15 -14
- package/src/extensions/delete.ts +89 -0
- package/src/extensions/index.ts +1 -0
- package/src/extensions/keymap.ts +4 -0
- package/src/helpers/getExtensionField.ts +10 -7
- package/src/index.ts +3 -7
- package/src/jsx-runtime.ts +64 -0
- package/src/types.ts +334 -19
- package/src/utilities/elementFromString.ts +3 -0
- package/src/utilities/index.ts +1 -0
- package/src/utilities/mergeAttributes.ts +1 -1
package/src/Extension.ts
CHANGED
|
@@ -1,502 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type ExtendableConfig, Extendable } from './Extendable.js'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import { InputRule } from './InputRule.js'
|
|
7
|
-
import { Mark } from './Mark.js'
|
|
8
|
-
import { Node } from './Node.js'
|
|
9
|
-
import { PasteRule } from './PasteRule.js'
|
|
10
|
-
import { AnyConfig, Extensions, GlobalAttributes, KeyboardShortcutCommand, ParentConfig, RawCommands } from './types.js'
|
|
11
|
-
import { callOrReturn } from './utilities/callOrReturn.js'
|
|
12
|
-
import { mergeDeep } from './utilities/mergeDeep.js'
|
|
13
|
-
|
|
14
|
-
declare module '@tiptap/core' {
|
|
15
|
-
interface ExtensionConfig<Options = any, Storage = any> {
|
|
16
|
-
// @ts-ignore - this is a dynamic key
|
|
17
|
-
[key: string]: any
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* The extension name - this must be unique.
|
|
21
|
-
* It will be used to identify the extension.
|
|
22
|
-
*
|
|
23
|
-
* @example 'myExtension'
|
|
24
|
-
*/
|
|
25
|
-
name: string
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* The priority of your extension. The higher, the earlier it will be called
|
|
29
|
-
* and will take precedence over other extensions with a lower priority.
|
|
30
|
-
* @default 100
|
|
31
|
-
* @example 101
|
|
32
|
-
*/
|
|
33
|
-
priority?: number
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* The default options for this extension.
|
|
37
|
-
* @example
|
|
38
|
-
* defaultOptions: {
|
|
39
|
-
* myOption: 'foo',
|
|
40
|
-
* myOtherOption: 10,
|
|
41
|
-
* }
|
|
42
|
-
*/
|
|
43
|
-
defaultOptions?: Options
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* This method will add options to this extension
|
|
47
|
-
* @see https://tiptap.dev/docs/editor/guide/custom-extensions#settings
|
|
48
|
-
* @example
|
|
49
|
-
* addOptions() {
|
|
50
|
-
* return {
|
|
51
|
-
* myOption: 'foo',
|
|
52
|
-
* myOtherOption: 10,
|
|
53
|
-
* }
|
|
54
|
-
*/
|
|
55
|
-
addOptions?: (this: {
|
|
56
|
-
name: string
|
|
57
|
-
parent: Exclude<ParentConfig<ExtensionConfig<Options, Storage>>['addOptions'], undefined>
|
|
58
|
-
}) => Options
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* The default storage this extension can save data to.
|
|
62
|
-
* @see https://tiptap.dev/docs/editor/guide/custom-extensions#storage
|
|
63
|
-
* @example
|
|
64
|
-
* defaultStorage: {
|
|
65
|
-
* prefetchedUsers: [],
|
|
66
|
-
* loading: false,
|
|
67
|
-
* }
|
|
68
|
-
*/
|
|
69
|
-
addStorage?: (this: {
|
|
70
|
-
name: string
|
|
71
|
-
options: Options
|
|
72
|
-
parent: Exclude<ParentConfig<ExtensionConfig<Options, Storage>>['addStorage'], undefined>
|
|
73
|
-
}) => Storage
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* This function adds globalAttributes to specific nodes.
|
|
77
|
-
* @see https://tiptap.dev/docs/editor/guide/custom-extensions#global-attributes
|
|
78
|
-
* @example
|
|
79
|
-
* addGlobalAttributes() {
|
|
80
|
-
* return [
|
|
81
|
-
* {
|
|
82
|
-
// Extend the following extensions
|
|
83
|
-
* types: [
|
|
84
|
-
* 'heading',
|
|
85
|
-
* 'paragraph',
|
|
86
|
-
* ],
|
|
87
|
-
* // … with those attributes
|
|
88
|
-
* attributes: {
|
|
89
|
-
* textAlign: {
|
|
90
|
-
* default: 'left',
|
|
91
|
-
* renderHTML: attributes => ({
|
|
92
|
-
* style: `text-align: ${attributes.textAlign}`,
|
|
93
|
-
* }),
|
|
94
|
-
* parseHTML: element => element.style.textAlign || 'left',
|
|
95
|
-
* },
|
|
96
|
-
* },
|
|
97
|
-
* },
|
|
98
|
-
* ]
|
|
99
|
-
* }
|
|
100
|
-
*/
|
|
101
|
-
addGlobalAttributes?: (this: {
|
|
102
|
-
name: string
|
|
103
|
-
options: Options
|
|
104
|
-
storage: Storage
|
|
105
|
-
extensions: (Node | Mark)[]
|
|
106
|
-
parent: ParentConfig<ExtensionConfig<Options, Storage>>['addGlobalAttributes']
|
|
107
|
-
}) => GlobalAttributes
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* This function adds commands to the editor
|
|
111
|
-
* @see https://tiptap.dev/docs/editor/guide/custom-extensions#commands
|
|
112
|
-
* @example
|
|
113
|
-
* addCommands() {
|
|
114
|
-
* return {
|
|
115
|
-
* myCommand: () => ({ chain }) => chain().setMark('type', 'foo').run(),
|
|
116
|
-
* }
|
|
117
|
-
* }
|
|
118
|
-
*/
|
|
119
|
-
addCommands?: (this: {
|
|
120
|
-
name: string
|
|
121
|
-
options: Options
|
|
122
|
-
storage: Storage
|
|
123
|
-
editor: Editor
|
|
124
|
-
parent: ParentConfig<ExtensionConfig<Options, Storage>>['addCommands']
|
|
125
|
-
}) => Partial<RawCommands>
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* This function registers keyboard shortcuts.
|
|
129
|
-
* @see https://tiptap.dev/docs/editor/guide/custom-extensions#keyboard-shortcuts
|
|
130
|
-
* @example
|
|
131
|
-
* addKeyboardShortcuts() {
|
|
132
|
-
* return {
|
|
133
|
-
* 'Mod-l': () => this.editor.commands.toggleBulletList(),
|
|
134
|
-
* }
|
|
135
|
-
* },
|
|
136
|
-
*/
|
|
137
|
-
addKeyboardShortcuts?: (this: {
|
|
138
|
-
name: string
|
|
139
|
-
options: Options
|
|
140
|
-
storage: Storage
|
|
141
|
-
editor: Editor
|
|
142
|
-
parent: ParentConfig<ExtensionConfig<Options, Storage>>['addKeyboardShortcuts']
|
|
143
|
-
}) => {
|
|
144
|
-
[key: string]: KeyboardShortcutCommand
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* This function adds input rules to the editor.
|
|
149
|
-
* @see https://tiptap.dev/docs/editor/guide/custom-extensions#input-rules
|
|
150
|
-
* @example
|
|
151
|
-
* addInputRules() {
|
|
152
|
-
* return [
|
|
153
|
-
* markInputRule({
|
|
154
|
-
* find: inputRegex,
|
|
155
|
-
* type: this.type,
|
|
156
|
-
* }),
|
|
157
|
-
* ]
|
|
158
|
-
* },
|
|
159
|
-
*/
|
|
160
|
-
addInputRules?: (this: {
|
|
161
|
-
name: string
|
|
162
|
-
options: Options
|
|
163
|
-
storage: Storage
|
|
164
|
-
editor: Editor
|
|
165
|
-
parent: ParentConfig<ExtensionConfig<Options, Storage>>['addInputRules']
|
|
166
|
-
}) => InputRule[]
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* This function adds paste rules to the editor.
|
|
170
|
-
* @see https://tiptap.dev/docs/editor/guide/custom-extensions#paste-rules
|
|
171
|
-
* @example
|
|
172
|
-
* addPasteRules() {
|
|
173
|
-
* return [
|
|
174
|
-
* markPasteRule({
|
|
175
|
-
* find: pasteRegex,
|
|
176
|
-
* type: this.type,
|
|
177
|
-
* }),
|
|
178
|
-
* ]
|
|
179
|
-
* },
|
|
180
|
-
*/
|
|
181
|
-
addPasteRules?: (this: {
|
|
182
|
-
name: string
|
|
183
|
-
options: Options
|
|
184
|
-
storage: Storage
|
|
185
|
-
editor: Editor
|
|
186
|
-
parent: ParentConfig<ExtensionConfig<Options, Storage>>['addPasteRules']
|
|
187
|
-
}) => PasteRule[]
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* This function adds Prosemirror plugins to the editor
|
|
191
|
-
* @see https://tiptap.dev/docs/editor/guide/custom-extensions#prosemirror-plugins
|
|
192
|
-
* @example
|
|
193
|
-
* addProseMirrorPlugins() {
|
|
194
|
-
* return [
|
|
195
|
-
* customPlugin(),
|
|
196
|
-
* ]
|
|
197
|
-
* }
|
|
198
|
-
*/
|
|
199
|
-
addProseMirrorPlugins?: (this: {
|
|
200
|
-
name: string
|
|
201
|
-
options: Options
|
|
202
|
-
storage: Storage
|
|
203
|
-
editor: Editor
|
|
204
|
-
parent: ParentConfig<ExtensionConfig<Options, Storage>>['addProseMirrorPlugins']
|
|
205
|
-
}) => Plugin[]
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* This function adds additional extensions to the editor. This is useful for
|
|
209
|
-
* building extension kits.
|
|
210
|
-
* @example
|
|
211
|
-
* addExtensions() {
|
|
212
|
-
* return [
|
|
213
|
-
* BulletList,
|
|
214
|
-
* OrderedList,
|
|
215
|
-
* ListItem
|
|
216
|
-
* ]
|
|
217
|
-
* }
|
|
218
|
-
*/
|
|
219
|
-
addExtensions?: (this: {
|
|
220
|
-
name: string
|
|
221
|
-
options: Options
|
|
222
|
-
storage: Storage
|
|
223
|
-
parent: ParentConfig<ExtensionConfig<Options, Storage>>['addExtensions']
|
|
224
|
-
}) => Extensions
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* This function extends the schema of the node.
|
|
228
|
-
* @example
|
|
229
|
-
* extendNodeSchema() {
|
|
230
|
-
* return {
|
|
231
|
-
* group: 'inline',
|
|
232
|
-
* selectable: false,
|
|
233
|
-
* }
|
|
234
|
-
* }
|
|
235
|
-
*/
|
|
236
|
-
extendNodeSchema?:
|
|
237
|
-
| ((
|
|
238
|
-
this: {
|
|
239
|
-
name: string
|
|
240
|
-
options: Options
|
|
241
|
-
storage: Storage
|
|
242
|
-
parent: ParentConfig<ExtensionConfig<Options, Storage>>['extendNodeSchema']
|
|
243
|
-
},
|
|
244
|
-
extension: Node,
|
|
245
|
-
) => Record<string, any>)
|
|
246
|
-
| null
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* This function extends the schema of the mark.
|
|
250
|
-
* @example
|
|
251
|
-
* extendMarkSchema() {
|
|
252
|
-
* return {
|
|
253
|
-
* group: 'inline',
|
|
254
|
-
* selectable: false,
|
|
255
|
-
* }
|
|
256
|
-
* }
|
|
257
|
-
*/
|
|
258
|
-
extendMarkSchema?:
|
|
259
|
-
| ((
|
|
260
|
-
this: {
|
|
261
|
-
name: string
|
|
262
|
-
options: Options
|
|
263
|
-
storage: Storage
|
|
264
|
-
parent: ParentConfig<ExtensionConfig<Options, Storage>>['extendMarkSchema']
|
|
265
|
-
},
|
|
266
|
-
extension: Mark,
|
|
267
|
-
) => Record<string, any>)
|
|
268
|
-
| null
|
|
269
|
-
|
|
270
|
-
/**
|
|
271
|
-
* The editor is not ready yet.
|
|
272
|
-
*/
|
|
273
|
-
onBeforeCreate?:
|
|
274
|
-
| ((this: {
|
|
275
|
-
name: string
|
|
276
|
-
options: Options
|
|
277
|
-
storage: Storage
|
|
278
|
-
editor: Editor
|
|
279
|
-
parent: ParentConfig<ExtensionConfig<Options, Storage>>['onBeforeCreate']
|
|
280
|
-
}) => void)
|
|
281
|
-
| null
|
|
282
|
-
|
|
283
|
-
/**
|
|
284
|
-
* The editor is ready.
|
|
285
|
-
*/
|
|
286
|
-
onCreate?:
|
|
287
|
-
| ((this: {
|
|
288
|
-
name: string
|
|
289
|
-
options: Options
|
|
290
|
-
storage: Storage
|
|
291
|
-
editor: Editor
|
|
292
|
-
parent: ParentConfig<ExtensionConfig<Options, Storage>>['onCreate']
|
|
293
|
-
}) => void)
|
|
294
|
-
| null
|
|
295
|
-
|
|
296
|
-
/**
|
|
297
|
-
* The content has changed.
|
|
298
|
-
*/
|
|
299
|
-
onUpdate?:
|
|
300
|
-
| ((this: {
|
|
301
|
-
name: string
|
|
302
|
-
options: Options
|
|
303
|
-
storage: Storage
|
|
304
|
-
editor: Editor
|
|
305
|
-
parent: ParentConfig<ExtensionConfig<Options, Storage>>['onUpdate']
|
|
306
|
-
}) => void)
|
|
307
|
-
| null
|
|
308
|
-
|
|
309
|
-
/**
|
|
310
|
-
* The selection has changed.
|
|
311
|
-
*/
|
|
312
|
-
onSelectionUpdate?:
|
|
313
|
-
| ((this: {
|
|
314
|
-
name: string
|
|
315
|
-
options: Options
|
|
316
|
-
storage: Storage
|
|
317
|
-
editor: Editor
|
|
318
|
-
parent: ParentConfig<ExtensionConfig<Options, Storage>>['onSelectionUpdate']
|
|
319
|
-
}) => void)
|
|
320
|
-
| null
|
|
321
|
-
|
|
322
|
-
/**
|
|
323
|
-
* The editor state has changed.
|
|
324
|
-
*/
|
|
325
|
-
onTransaction?:
|
|
326
|
-
| ((
|
|
327
|
-
this: {
|
|
328
|
-
name: string
|
|
329
|
-
options: Options
|
|
330
|
-
storage: Storage
|
|
331
|
-
editor: Editor
|
|
332
|
-
parent: ParentConfig<ExtensionConfig<Options, Storage>>['onTransaction']
|
|
333
|
-
},
|
|
334
|
-
props: {
|
|
335
|
-
editor: Editor
|
|
336
|
-
transaction: Transaction
|
|
337
|
-
},
|
|
338
|
-
) => void)
|
|
339
|
-
| null
|
|
340
|
-
|
|
341
|
-
/**
|
|
342
|
-
* The editor is focused.
|
|
343
|
-
*/
|
|
344
|
-
onFocus?:
|
|
345
|
-
| ((
|
|
346
|
-
this: {
|
|
347
|
-
name: string
|
|
348
|
-
options: Options
|
|
349
|
-
storage: Storage
|
|
350
|
-
editor: Editor
|
|
351
|
-
parent: ParentConfig<ExtensionConfig<Options, Storage>>['onFocus']
|
|
352
|
-
},
|
|
353
|
-
props: {
|
|
354
|
-
event: FocusEvent
|
|
355
|
-
},
|
|
356
|
-
) => void)
|
|
357
|
-
| null
|
|
358
|
-
|
|
359
|
-
/**
|
|
360
|
-
* The editor isn’t focused anymore.
|
|
361
|
-
*/
|
|
362
|
-
onBlur?:
|
|
363
|
-
| ((
|
|
364
|
-
this: {
|
|
365
|
-
name: string
|
|
366
|
-
options: Options
|
|
367
|
-
storage: Storage
|
|
368
|
-
editor: Editor
|
|
369
|
-
parent: ParentConfig<ExtensionConfig<Options, Storage>>['onBlur']
|
|
370
|
-
},
|
|
371
|
-
props: {
|
|
372
|
-
event: FocusEvent
|
|
373
|
-
},
|
|
374
|
-
) => void)
|
|
375
|
-
| null
|
|
376
|
-
|
|
377
|
-
/**
|
|
378
|
-
* The editor is destroyed.
|
|
379
|
-
*/
|
|
380
|
-
onDestroy?:
|
|
381
|
-
| ((this: {
|
|
382
|
-
name: string
|
|
383
|
-
options: Options
|
|
384
|
-
storage: Storage
|
|
385
|
-
editor: Editor
|
|
386
|
-
parent: ParentConfig<ExtensionConfig<Options, Storage>>['onDestroy']
|
|
387
|
-
}) => void)
|
|
388
|
-
| null
|
|
389
|
-
}
|
|
390
|
-
}
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
4
|
+
export interface ExtensionConfig<Options = any, Storage = any>
|
|
5
|
+
extends ExtendableConfig<Options, Storage, ExtensionConfig<Options, Storage>, null> {}
|
|
391
6
|
|
|
392
7
|
/**
|
|
393
8
|
* The Extension class is the base class for all extensions.
|
|
394
9
|
* @see https://tiptap.dev/api/extensions#create-a-new-extension
|
|
395
10
|
*/
|
|
396
|
-
export class Extension<Options = any, Storage = any> {
|
|
11
|
+
export class Extension<Options = any, Storage = any> extends Extendable<Options, Storage> {
|
|
397
12
|
type = 'extension'
|
|
398
13
|
|
|
399
|
-
name = 'extension'
|
|
400
|
-
|
|
401
|
-
parent: Extension | null = null
|
|
402
|
-
|
|
403
|
-
child: Extension | null = null
|
|
404
|
-
|
|
405
|
-
options: Options
|
|
406
|
-
|
|
407
|
-
storage: Storage
|
|
408
|
-
|
|
409
|
-
config: ExtensionConfig = {
|
|
410
|
-
name: this.name,
|
|
411
|
-
defaultOptions: {},
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
constructor(config: Partial<ExtensionConfig<Options, Storage>> = {}) {
|
|
415
|
-
this.config = {
|
|
416
|
-
...this.config,
|
|
417
|
-
...config,
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
this.name = this.config.name
|
|
421
|
-
|
|
422
|
-
if (config.defaultOptions && Object.keys(config.defaultOptions).length > 0) {
|
|
423
|
-
console.warn(
|
|
424
|
-
`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${this.name}".`,
|
|
425
|
-
)
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
// TODO: remove `addOptions` fallback
|
|
429
|
-
this.options = this.config.defaultOptions
|
|
430
|
-
|
|
431
|
-
if (this.config.addOptions) {
|
|
432
|
-
this.options = callOrReturn(
|
|
433
|
-
getExtensionField<AnyConfig['addOptions']>(this, 'addOptions', {
|
|
434
|
-
name: this.name,
|
|
435
|
-
}),
|
|
436
|
-
)
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
this.storage =
|
|
440
|
-
callOrReturn(
|
|
441
|
-
getExtensionField<AnyConfig['addStorage']>(this, 'addStorage', {
|
|
442
|
-
name: this.name,
|
|
443
|
-
options: this.options,
|
|
444
|
-
}),
|
|
445
|
-
) || {}
|
|
446
|
-
}
|
|
447
|
-
|
|
448
14
|
static create<O = any, S = any>(config: Partial<ExtensionConfig<O, S>> = {}) {
|
|
449
15
|
return new Extension<O, S>(config)
|
|
450
16
|
}
|
|
451
|
-
|
|
452
|
-
configure(options: Partial<Options> = {}) {
|
|
453
|
-
// return a new instance so we can use the same extension
|
|
454
|
-
// with different calls of `configure`
|
|
455
|
-
const extension = this.extend<Options, Storage>({
|
|
456
|
-
...this.config,
|
|
457
|
-
addOptions: () => {
|
|
458
|
-
return mergeDeep(this.options as Record<string, any>, options) as Options
|
|
459
|
-
},
|
|
460
|
-
})
|
|
461
|
-
|
|
462
|
-
// Always preserve the current name
|
|
463
|
-
extension.name = this.name
|
|
464
|
-
// Set the parent to be our parent
|
|
465
|
-
extension.parent = this.parent
|
|
466
|
-
|
|
467
|
-
return extension
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
extend<ExtendedOptions = Options, ExtendedStorage = Storage>(
|
|
471
|
-
extendedConfig: Partial<ExtensionConfig<ExtendedOptions, ExtendedStorage>> = {},
|
|
472
|
-
) {
|
|
473
|
-
const extension = new Extension<ExtendedOptions, ExtendedStorage>({ ...this.config, ...extendedConfig })
|
|
474
|
-
|
|
475
|
-
extension.parent = this
|
|
476
|
-
|
|
477
|
-
this.child = extension
|
|
478
|
-
|
|
479
|
-
extension.name = extendedConfig.name ? extendedConfig.name : extension.parent.name
|
|
480
|
-
|
|
481
|
-
if (extendedConfig.defaultOptions && Object.keys(extendedConfig.defaultOptions).length > 0) {
|
|
482
|
-
console.warn(
|
|
483
|
-
`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${extension.name}".`,
|
|
484
|
-
)
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
extension.options = callOrReturn(
|
|
488
|
-
getExtensionField<AnyConfig['addOptions']>(extension, 'addOptions', {
|
|
489
|
-
name: extension.name,
|
|
490
|
-
}),
|
|
491
|
-
)
|
|
492
|
-
|
|
493
|
-
extension.storage = callOrReturn(
|
|
494
|
-
getExtensionField<AnyConfig['addStorage']>(extension, 'addStorage', {
|
|
495
|
-
name: extension.name,
|
|
496
|
-
options: extension.options,
|
|
497
|
-
}),
|
|
498
|
-
)
|
|
499
|
-
|
|
500
|
-
return extension
|
|
501
|
-
}
|
|
502
17
|
}
|
package/src/ExtensionManager.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { keymap } from '@tiptap/pm/keymap'
|
|
2
2
|
import { Schema } from '@tiptap/pm/model'
|
|
3
3
|
import { Plugin } from '@tiptap/pm/state'
|
|
4
|
-
import { NodeViewConstructor } from '@tiptap/pm/view'
|
|
4
|
+
import { MarkViewConstructor, NodeViewConstructor } from '@tiptap/pm/view'
|
|
5
5
|
|
|
6
6
|
import type { Editor } from './Editor.js'
|
|
7
7
|
import {
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
sortExtensions,
|
|
18
18
|
splitExtensions,
|
|
19
19
|
} from './helpers/index.js'
|
|
20
|
-
import type
|
|
20
|
+
import { type MarkConfig, type NodeConfig, type Storage, getMarkType } from './index.js'
|
|
21
21
|
import { InputRule, inputRulesPlugin } from './InputRule.js'
|
|
22
22
|
import { Mark } from './Mark.js'
|
|
23
23
|
import { PasteRule, pasteRulesPlugin } from './PasteRule.js'
|
|
@@ -55,7 +55,7 @@ export class ExtensionManager {
|
|
|
55
55
|
const context = {
|
|
56
56
|
name: extension.name,
|
|
57
57
|
options: extension.options,
|
|
58
|
-
storage: extension.
|
|
58
|
+
storage: this.editor.extensionStorage[extension.name as keyof Storage],
|
|
59
59
|
editor: this.editor,
|
|
60
60
|
type: getSchemaTypeByName(extension.name, this.schema),
|
|
61
61
|
}
|
|
@@ -95,7 +95,7 @@ export class ExtensionManager {
|
|
|
95
95
|
const context = {
|
|
96
96
|
name: extension.name,
|
|
97
97
|
options: extension.options,
|
|
98
|
-
storage: extension.
|
|
98
|
+
storage: this.editor.extensionStorage[extension.name as keyof Storage],
|
|
99
99
|
editor,
|
|
100
100
|
type: getSchemaTypeByName(extension.name, this.schema),
|
|
101
101
|
}
|
|
@@ -111,7 +111,7 @@ export class ExtensionManager {
|
|
|
111
111
|
let defaultBindings: Record<string, () => boolean> = {}
|
|
112
112
|
|
|
113
113
|
// bind exit handling
|
|
114
|
-
if (extension.type === 'mark' && getExtensionField<
|
|
114
|
+
if (extension.type === 'mark' && getExtensionField<MarkConfig['exitable']>(extension, 'exitable', context)) {
|
|
115
115
|
defaultBindings.ArrowRight = () => Mark.handleExit({ editor, mark: extension as Mark })
|
|
116
116
|
}
|
|
117
117
|
|
|
@@ -194,7 +194,7 @@ export class ExtensionManager {
|
|
|
194
194
|
const context = {
|
|
195
195
|
name: extension.name,
|
|
196
196
|
options: extension.options,
|
|
197
|
-
storage: extension.
|
|
197
|
+
storage: this.editor.extensionStorage[extension.name as keyof Storage],
|
|
198
198
|
editor,
|
|
199
199
|
type: getNodeType(extension.name, this.schema),
|
|
200
200
|
}
|
|
@@ -226,19 +226,64 @@ export class ExtensionManager {
|
|
|
226
226
|
)
|
|
227
227
|
}
|
|
228
228
|
|
|
229
|
+
get markViews(): Record<string, MarkViewConstructor> {
|
|
230
|
+
const { editor } = this
|
|
231
|
+
const { markExtensions } = splitExtensions(this.extensions)
|
|
232
|
+
|
|
233
|
+
return Object.fromEntries(
|
|
234
|
+
markExtensions
|
|
235
|
+
.filter(extension => !!getExtensionField(extension, 'addMarkView'))
|
|
236
|
+
.map(extension => {
|
|
237
|
+
const extensionAttributes = this.attributes.filter(attribute => attribute.type === extension.name)
|
|
238
|
+
const context = {
|
|
239
|
+
name: extension.name,
|
|
240
|
+
options: extension.options,
|
|
241
|
+
storage: this.editor.extensionStorage[extension.name as keyof Storage],
|
|
242
|
+
editor,
|
|
243
|
+
type: getMarkType(extension.name, this.schema),
|
|
244
|
+
}
|
|
245
|
+
const addMarkView = getExtensionField<MarkConfig['addMarkView']>(extension, 'addMarkView', context)
|
|
246
|
+
|
|
247
|
+
if (!addMarkView) {
|
|
248
|
+
return []
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const markView: MarkViewConstructor = (mark, view, inline) => {
|
|
252
|
+
const HTMLAttributes = getRenderedAttributes(mark, extensionAttributes)
|
|
253
|
+
|
|
254
|
+
return addMarkView()({
|
|
255
|
+
// pass-through
|
|
256
|
+
mark,
|
|
257
|
+
view,
|
|
258
|
+
inline,
|
|
259
|
+
// tiptap-specific
|
|
260
|
+
editor,
|
|
261
|
+
extension,
|
|
262
|
+
HTMLAttributes,
|
|
263
|
+
})
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return [extension.name, markView]
|
|
267
|
+
}),
|
|
268
|
+
)
|
|
269
|
+
}
|
|
270
|
+
|
|
229
271
|
/**
|
|
230
272
|
* Go through all extensions, create extension storages & setup marks
|
|
231
273
|
* & bind editor event listener.
|
|
232
274
|
*/
|
|
233
275
|
private setupExtensions() {
|
|
234
|
-
this.extensions
|
|
235
|
-
|
|
236
|
-
|
|
276
|
+
const extensions = this.extensions
|
|
277
|
+
// re-initialize the extension storage object instance
|
|
278
|
+
this.editor.extensionStorage = Object.fromEntries(
|
|
279
|
+
extensions.map(extension => [extension.name, extension.storage]),
|
|
280
|
+
) as unknown as Storage
|
|
237
281
|
|
|
282
|
+
extensions.forEach(extension => {
|
|
238
283
|
const context = {
|
|
239
284
|
name: extension.name,
|
|
240
285
|
options: extension.options,
|
|
241
|
-
storage: extension.
|
|
286
|
+
storage: this.editor.extensionStorage[extension.name as keyof Storage],
|
|
242
287
|
editor: this.editor,
|
|
243
288
|
type: getSchemaTypeByName(extension.name, this.schema),
|
|
244
289
|
}
|