@tiptap/core 3.0.0-next.3 → 3.0.0-next.5
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 +21 -0
- package/README.md +5 -1
- package/dist/index.cjs +2627 -2651
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2423 -2688
- package/dist/index.d.ts +2423 -2688
- package/dist/index.js +2639 -2684
- 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 +27 -6
- package/src/CommandManager.ts +2 -9
- package/src/Editor.ts +191 -94
- package/src/EventEmitter.ts +7 -10
- package/src/Extendable.ts +483 -0
- package/src/Extension.ts +5 -496
- package/src/ExtensionManager.ts +81 -135
- package/src/InputRule.ts +35 -48
- package/src/Mark.ts +135 -623
- package/src/MarkView.ts +66 -0
- package/src/Node.ts +325 -829
- package/src/NodePos.ts +1 -3
- package/src/NodeView.ts +10 -20
- package/src/PasteRule.ts +43 -55
- package/src/Tracker.ts +7 -9
- package/src/commands/blur.ts +14 -12
- package/src/commands/clearContent.ts +12 -5
- package/src/commands/clearNodes.ts +32 -30
- package/src/commands/command.ts +1 -1
- package/src/commands/createParagraphNear.ts +5 -3
- package/src/commands/cut.ts +12 -10
- package/src/commands/deleteCurrentNode.ts +23 -21
- package/src/commands/deleteNode.ts +18 -16
- package/src/commands/deleteRange.ts +10 -8
- package/src/commands/deleteSelection.ts +5 -3
- package/src/commands/enter.ts +6 -4
- package/src/commands/exitCode.ts +5 -3
- package/src/commands/extendMarkRange.ts +14 -12
- package/src/commands/first.ts +2 -4
- package/src/commands/focus.ts +51 -48
- package/src/commands/forEach.ts +2 -2
- package/src/commands/insertContent.ts +12 -14
- package/src/commands/insertContentAt.ts +105 -98
- package/src/commands/join.ts +20 -12
- package/src/commands/joinItemBackward.ts +16 -18
- package/src/commands/joinItemForward.ts +16 -18
- package/src/commands/joinTextblockBackward.ts +5 -3
- package/src/commands/joinTextblockForward.ts +5 -3
- package/src/commands/keyboardShortcut.ts +29 -34
- package/src/commands/lift.ts +10 -8
- package/src/commands/liftEmptyBlock.ts +6 -4
- package/src/commands/liftListItem.ts +6 -4
- package/src/commands/newlineInCode.ts +5 -3
- package/src/commands/resetAttributes.ts +36 -41
- package/src/commands/scrollIntoView.ts +9 -7
- package/src/commands/selectAll.ts +10 -8
- package/src/commands/selectNodeBackward.ts +5 -3
- package/src/commands/selectNodeForward.ts +5 -3
- package/src/commands/selectParentNode.ts +5 -3
- package/src/commands/selectTextblockEnd.ts +5 -3
- package/src/commands/selectTextblockStart.ts +5 -3
- package/src/commands/setContent.ts +37 -36
- package/src/commands/setMark.ts +55 -57
- package/src/commands/setMeta.ts +7 -5
- package/src/commands/setNode.ts +32 -30
- package/src/commands/setNodeSelection.ts +11 -9
- package/src/commands/setTextSelection.ts +15 -13
- package/src/commands/sinkListItem.ts +6 -4
- package/src/commands/splitBlock.ts +67 -76
- package/src/commands/splitListItem.ts +93 -106
- package/src/commands/toggleList.ts +73 -71
- package/src/commands/toggleMark.ts +11 -9
- package/src/commands/toggleNode.ts +18 -16
- package/src/commands/toggleWrap.ts +10 -8
- package/src/commands/undoInputRule.ts +31 -29
- package/src/commands/unsetAllMarks.ts +16 -14
- package/src/commands/unsetMark.ts +27 -25
- package/src/commands/updateAttributes.ts +92 -100
- package/src/commands/wrapIn.ts +6 -4
- package/src/commands/wrapInList.ts +6 -4
- package/src/extensions/clipboardTextSerializer.ts +2 -4
- package/src/extensions/delete.ts +89 -0
- package/src/extensions/focusEvents.ts +2 -6
- package/src/extensions/index.ts +1 -0
- package/src/extensions/keymap.ts +58 -50
- package/src/extensions/paste.ts +0 -1
- package/src/extensions/tabindex.ts +1 -1
- package/src/helpers/combineTransactionSteps.ts +1 -4
- package/src/helpers/createChainableState.ts +1 -4
- package/src/helpers/createDocument.ts +1 -3
- package/src/helpers/createNodeFromContent.ts +4 -10
- package/src/helpers/findChildrenInRange.ts +1 -5
- package/src/helpers/findParentNode.ts +3 -1
- package/src/helpers/flattenExtensions.ts +30 -0
- package/src/helpers/getAttributes.ts +1 -4
- package/src/helpers/getAttributesFromExtensions.ts +28 -37
- package/src/helpers/getChangedRanges.ts +13 -11
- package/src/helpers/getExtensionField.ts +11 -11
- package/src/helpers/getMarkAttributes.ts +1 -4
- package/src/helpers/getMarkRange.ts +5 -15
- package/src/helpers/getMarkType.ts +1 -3
- package/src/helpers/getNodeAttributes.ts +1 -4
- package/src/helpers/getNodeType.ts +1 -3
- package/src/helpers/getRenderedAttributes.ts +1 -3
- package/src/helpers/getSchema.ts +2 -2
- package/src/helpers/getSchemaByResolvedExtensions.ts +45 -77
- package/src/helpers/getSplittedAttributes.ts +4 -4
- package/src/helpers/getTextContentFromNodes.ts +8 -11
- package/src/helpers/index.ts +4 -0
- package/src/helpers/injectExtensionAttributesToParseRule.ts +1 -1
- package/src/helpers/isActive.ts +1 -5
- package/src/helpers/isExtensionRulesEnabled.ts +1 -3
- package/src/helpers/isNodeEmpty.ts +2 -2
- package/src/helpers/resolveExtensions.ts +25 -0
- package/src/helpers/resolveFocusPosition.ts +3 -14
- package/src/helpers/rewriteUnknownContent.ts +149 -0
- package/src/helpers/sortExtensions.ts +26 -0
- package/src/index.ts +3 -7
- package/src/inputRules/markInputRule.ts +1 -5
- package/src/inputRules/nodeInputRule.ts +2 -9
- package/src/inputRules/textInputRule.ts +1 -4
- package/src/inputRules/textblockTypeInputRule.ts +2 -8
- package/src/inputRules/wrappingInputRule.ts +13 -19
- package/src/jsx-runtime.ts +64 -0
- package/src/pasteRules/markPasteRule.ts +1 -3
- package/src/pasteRules/nodePasteRule.ts +2 -8
- package/src/pasteRules/textPasteRule.ts +1 -4
- package/src/types.ts +529 -174
- package/src/utilities/createStyleTag.ts +3 -1
- package/src/utilities/deleteProps.ts +7 -11
- package/src/utilities/elementFromString.ts +3 -0
- package/src/utilities/findDuplicates.ts +4 -1
- package/src/utilities/index.ts +1 -0
- package/src/utilities/isFunction.ts +1 -0
- package/src/utilities/isMacOS.ts +1 -3
- package/src/utilities/isiOS.ts +5 -10
- package/src/utilities/mergeAttributes.ts +17 -7
- package/src/utilities/removeDuplicates.ts +1 -3
package/src/ExtensionManager.ts
CHANGED
|
@@ -1,24 +1,28 @@
|
|
|
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
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
7
|
+
import {
|
|
8
|
+
flattenExtensions,
|
|
9
|
+
getAttributesFromExtensions,
|
|
10
|
+
getExtensionField,
|
|
11
|
+
getNodeType,
|
|
12
|
+
getRenderedAttributes,
|
|
13
|
+
getSchemaByResolvedExtensions,
|
|
14
|
+
getSchemaTypeByName,
|
|
15
|
+
isExtensionRulesEnabled,
|
|
16
|
+
resolveExtensions,
|
|
17
|
+
sortExtensions,
|
|
18
|
+
splitExtensions,
|
|
19
|
+
} from './helpers/index.js'
|
|
20
|
+
import { type MarkConfig, type NodeConfig, type Storage, getMarkType } from './index.js'
|
|
16
21
|
import { InputRule, inputRulesPlugin } from './InputRule.js'
|
|
17
22
|
import { Mark } from './Mark.js'
|
|
18
23
|
import { PasteRule, pasteRulesPlugin } from './PasteRule.js'
|
|
19
24
|
import { AnyConfig, Extensions, RawCommands } from './types.js'
|
|
20
25
|
import { callOrReturn } from './utilities/callOrReturn.js'
|
|
21
|
-
import { findDuplicates } from './utilities/findDuplicates.js'
|
|
22
26
|
|
|
23
27
|
export class ExtensionManager {
|
|
24
28
|
editor: Editor
|
|
@@ -31,87 +35,16 @@ export class ExtensionManager {
|
|
|
31
35
|
|
|
32
36
|
constructor(extensions: Extensions, editor: Editor) {
|
|
33
37
|
this.editor = editor
|
|
34
|
-
this.extensions =
|
|
38
|
+
this.extensions = resolveExtensions(extensions)
|
|
35
39
|
this.schema = getSchemaByResolvedExtensions(this.extensions, editor)
|
|
36
40
|
this.setupExtensions()
|
|
37
41
|
}
|
|
38
42
|
|
|
39
|
-
|
|
40
|
-
* Returns a flattened and sorted extension list while
|
|
41
|
-
* also checking for duplicated extensions and warns the user.
|
|
42
|
-
* @param extensions An array of Tiptap extensions
|
|
43
|
-
* @returns An flattened and sorted array of Tiptap extensions
|
|
44
|
-
*/
|
|
45
|
-
static resolve(extensions: Extensions): Extensions {
|
|
46
|
-
const resolvedExtensions = ExtensionManager.sort(ExtensionManager.flatten(extensions))
|
|
47
|
-
const duplicatedNames = findDuplicates(resolvedExtensions.map(extension => extension.name))
|
|
48
|
-
|
|
49
|
-
if (duplicatedNames.length) {
|
|
50
|
-
console.warn(
|
|
51
|
-
`[tiptap warn]: Duplicate extension names found: [${duplicatedNames
|
|
52
|
-
.map(item => `'${item}'`)
|
|
53
|
-
.join(', ')}]. This can lead to issues.`,
|
|
54
|
-
)
|
|
55
|
-
}
|
|
43
|
+
static resolve = resolveExtensions
|
|
56
44
|
|
|
57
|
-
|
|
58
|
-
}
|
|
45
|
+
static sort = sortExtensions
|
|
59
46
|
|
|
60
|
-
|
|
61
|
-
* Create a flattened array of extensions by traversing the `addExtensions` field.
|
|
62
|
-
* @param extensions An array of Tiptap extensions
|
|
63
|
-
* @returns A flattened array of Tiptap extensions
|
|
64
|
-
*/
|
|
65
|
-
static flatten(extensions: Extensions): Extensions {
|
|
66
|
-
return (
|
|
67
|
-
extensions
|
|
68
|
-
.map(extension => {
|
|
69
|
-
const context = {
|
|
70
|
-
name: extension.name,
|
|
71
|
-
options: extension.options,
|
|
72
|
-
storage: extension.storage,
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const addExtensions = getExtensionField<AnyConfig['addExtensions']>(
|
|
76
|
-
extension,
|
|
77
|
-
'addExtensions',
|
|
78
|
-
context,
|
|
79
|
-
)
|
|
80
|
-
|
|
81
|
-
if (addExtensions) {
|
|
82
|
-
return [extension, ...this.flatten(addExtensions())]
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return extension
|
|
86
|
-
})
|
|
87
|
-
// `Infinity` will break TypeScript so we set a number that is probably high enough
|
|
88
|
-
.flat(10)
|
|
89
|
-
)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Sort extensions by priority.
|
|
94
|
-
* @param extensions An array of Tiptap extensions
|
|
95
|
-
* @returns A sorted array of Tiptap extensions by priority
|
|
96
|
-
*/
|
|
97
|
-
static sort(extensions: Extensions): Extensions {
|
|
98
|
-
const defaultPriority = 100
|
|
99
|
-
|
|
100
|
-
return extensions.sort((a, b) => {
|
|
101
|
-
const priorityA = getExtensionField<AnyConfig['priority']>(a, 'priority') || defaultPriority
|
|
102
|
-
const priorityB = getExtensionField<AnyConfig['priority']>(b, 'priority') || defaultPriority
|
|
103
|
-
|
|
104
|
-
if (priorityA > priorityB) {
|
|
105
|
-
return -1
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
if (priorityA < priorityB) {
|
|
109
|
-
return 1
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return 0
|
|
113
|
-
})
|
|
114
|
-
}
|
|
47
|
+
static flatten = flattenExtensions
|
|
115
48
|
|
|
116
49
|
/**
|
|
117
50
|
* Get all commands from the extensions.
|
|
@@ -122,16 +55,12 @@ export class ExtensionManager {
|
|
|
122
55
|
const context = {
|
|
123
56
|
name: extension.name,
|
|
124
57
|
options: extension.options,
|
|
125
|
-
storage: extension.
|
|
58
|
+
storage: this.editor.extensionStorage[extension.name as keyof Storage],
|
|
126
59
|
editor: this.editor,
|
|
127
60
|
type: getSchemaTypeByName(extension.name, this.schema),
|
|
128
61
|
}
|
|
129
62
|
|
|
130
|
-
const addCommands = getExtensionField<AnyConfig['addCommands']>(
|
|
131
|
-
extension,
|
|
132
|
-
'addCommands',
|
|
133
|
-
context,
|
|
134
|
-
)
|
|
63
|
+
const addCommands = getExtensionField<AnyConfig['addCommands']>(extension, 'addCommands', context)
|
|
135
64
|
|
|
136
65
|
if (!addCommands) {
|
|
137
66
|
return commands
|
|
@@ -156,7 +85,7 @@ export class ExtensionManager {
|
|
|
156
85
|
// so it feels more natural to run plugins at the end of an array first.
|
|
157
86
|
// That’s why we have to reverse the `extensions` array and sort again
|
|
158
87
|
// based on the `priority` option.
|
|
159
|
-
const extensions =
|
|
88
|
+
const extensions = sortExtensions([...this.extensions].reverse())
|
|
160
89
|
|
|
161
90
|
const inputRules: InputRule[] = []
|
|
162
91
|
const pasteRules: PasteRule[] = []
|
|
@@ -166,7 +95,7 @@ export class ExtensionManager {
|
|
|
166
95
|
const context = {
|
|
167
96
|
name: extension.name,
|
|
168
97
|
options: extension.options,
|
|
169
|
-
storage: extension.
|
|
98
|
+
storage: this.editor.extensionStorage[extension.name as keyof Storage],
|
|
170
99
|
editor,
|
|
171
100
|
type: getSchemaTypeByName(extension.name, this.schema),
|
|
172
101
|
}
|
|
@@ -182,7 +111,7 @@ export class ExtensionManager {
|
|
|
182
111
|
let defaultBindings: Record<string, () => boolean> = {}
|
|
183
112
|
|
|
184
113
|
// bind exit handling
|
|
185
|
-
if (extension.type === 'mark' && getExtensionField<
|
|
114
|
+
if (extension.type === 'mark' && getExtensionField<MarkConfig['exitable']>(extension, 'exitable', context)) {
|
|
186
115
|
defaultBindings.ArrowRight = () => Mark.handleExit({ editor, mark: extension as Mark })
|
|
187
116
|
}
|
|
188
117
|
|
|
@@ -200,21 +129,13 @@ export class ExtensionManager {
|
|
|
200
129
|
|
|
201
130
|
plugins.push(keyMapPlugin)
|
|
202
131
|
|
|
203
|
-
const addInputRules = getExtensionField<AnyConfig['addInputRules']>(
|
|
204
|
-
extension,
|
|
205
|
-
'addInputRules',
|
|
206
|
-
context,
|
|
207
|
-
)
|
|
132
|
+
const addInputRules = getExtensionField<AnyConfig['addInputRules']>(extension, 'addInputRules', context)
|
|
208
133
|
|
|
209
134
|
if (isExtensionRulesEnabled(extension, editor.options.enableInputRules) && addInputRules) {
|
|
210
135
|
inputRules.push(...addInputRules())
|
|
211
136
|
}
|
|
212
137
|
|
|
213
|
-
const addPasteRules = getExtensionField<AnyConfig['addPasteRules']>(
|
|
214
|
-
extension,
|
|
215
|
-
'addPasteRules',
|
|
216
|
-
context,
|
|
217
|
-
)
|
|
138
|
+
const addPasteRules = getExtensionField<AnyConfig['addPasteRules']>(extension, 'addPasteRules', context)
|
|
218
139
|
|
|
219
140
|
if (isExtensionRulesEnabled(extension, editor.options.enablePasteRules) && addPasteRules) {
|
|
220
141
|
pasteRules.push(...addPasteRules())
|
|
@@ -269,33 +190,21 @@ export class ExtensionManager {
|
|
|
269
190
|
nodeExtensions
|
|
270
191
|
.filter(extension => !!getExtensionField(extension, 'addNodeView'))
|
|
271
192
|
.map(extension => {
|
|
272
|
-
const extensionAttributes = this.attributes.filter(
|
|
273
|
-
attribute => attribute.type === extension.name,
|
|
274
|
-
)
|
|
193
|
+
const extensionAttributes = this.attributes.filter(attribute => attribute.type === extension.name)
|
|
275
194
|
const context = {
|
|
276
195
|
name: extension.name,
|
|
277
196
|
options: extension.options,
|
|
278
|
-
storage: extension.
|
|
197
|
+
storage: this.editor.extensionStorage[extension.name as keyof Storage],
|
|
279
198
|
editor,
|
|
280
199
|
type: getNodeType(extension.name, this.schema),
|
|
281
200
|
}
|
|
282
|
-
const addNodeView = getExtensionField<NodeConfig['addNodeView']>(
|
|
283
|
-
extension,
|
|
284
|
-
'addNodeView',
|
|
285
|
-
context,
|
|
286
|
-
)
|
|
201
|
+
const addNodeView = getExtensionField<NodeConfig['addNodeView']>(extension, 'addNodeView', context)
|
|
287
202
|
|
|
288
203
|
if (!addNodeView) {
|
|
289
204
|
return []
|
|
290
205
|
}
|
|
291
206
|
|
|
292
|
-
const nodeview: NodeViewConstructor = (
|
|
293
|
-
node,
|
|
294
|
-
view,
|
|
295
|
-
getPos,
|
|
296
|
-
decorations,
|
|
297
|
-
innerDecorations,
|
|
298
|
-
) => {
|
|
207
|
+
const nodeview: NodeViewConstructor = (node, view, getPos, decorations, innerDecorations) => {
|
|
299
208
|
const HTMLAttributes = getRenderedAttributes(node, extensionAttributes)
|
|
300
209
|
|
|
301
210
|
return addNodeView()({
|
|
@@ -317,19 +226,64 @@ export class ExtensionManager {
|
|
|
317
226
|
)
|
|
318
227
|
}
|
|
319
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
|
+
|
|
320
271
|
/**
|
|
321
272
|
* Go through all extensions, create extension storages & setup marks
|
|
322
273
|
* & bind editor event listener.
|
|
323
274
|
*/
|
|
324
275
|
private setupExtensions() {
|
|
325
|
-
this.extensions
|
|
326
|
-
|
|
327
|
-
|
|
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
|
|
328
281
|
|
|
282
|
+
extensions.forEach(extension => {
|
|
329
283
|
const context = {
|
|
330
284
|
name: extension.name,
|
|
331
285
|
options: extension.options,
|
|
332
|
-
storage: extension.
|
|
286
|
+
storage: this.editor.extensionStorage[extension.name as keyof Storage],
|
|
333
287
|
editor: this.editor,
|
|
334
288
|
type: getSchemaTypeByName(extension.name, this.schema),
|
|
335
289
|
}
|
|
@@ -342,11 +296,7 @@ export class ExtensionManager {
|
|
|
342
296
|
}
|
|
343
297
|
}
|
|
344
298
|
|
|
345
|
-
const onBeforeCreate = getExtensionField<AnyConfig['onBeforeCreate']>(
|
|
346
|
-
extension,
|
|
347
|
-
'onBeforeCreate',
|
|
348
|
-
context,
|
|
349
|
-
)
|
|
299
|
+
const onBeforeCreate = getExtensionField<AnyConfig['onBeforeCreate']>(extension, 'onBeforeCreate', context)
|
|
350
300
|
const onCreate = getExtensionField<AnyConfig['onCreate']>(extension, 'onCreate', context)
|
|
351
301
|
const onUpdate = getExtensionField<AnyConfig['onUpdate']>(extension, 'onUpdate', context)
|
|
352
302
|
const onSelectionUpdate = getExtensionField<AnyConfig['onSelectionUpdate']>(
|
|
@@ -354,11 +304,7 @@ export class ExtensionManager {
|
|
|
354
304
|
'onSelectionUpdate',
|
|
355
305
|
context,
|
|
356
306
|
)
|
|
357
|
-
const onTransaction = getExtensionField<AnyConfig['onTransaction']>(
|
|
358
|
-
extension,
|
|
359
|
-
'onTransaction',
|
|
360
|
-
context,
|
|
361
|
-
)
|
|
307
|
+
const onTransaction = getExtensionField<AnyConfig['onTransaction']>(extension, 'onTransaction', context)
|
|
362
308
|
const onFocus = getExtensionField<AnyConfig['onFocus']>(extension, 'onFocus', context)
|
|
363
309
|
const onBlur = getExtensionField<AnyConfig['onBlur']>(extension, 'onBlur', context)
|
|
364
310
|
const onDestroy = getExtensionField<AnyConfig['onDestroy']>(extension, 'onDestroy', context)
|
package/src/InputRule.ts
CHANGED
|
@@ -6,57 +6,48 @@ import { Editor } from './Editor.js'
|
|
|
6
6
|
import { createChainableState } from './helpers/createChainableState.js'
|
|
7
7
|
import { getHTMLFromFragment } from './helpers/getHTMLFromFragment.js'
|
|
8
8
|
import { getTextContentFromNodes } from './helpers/getTextContentFromNodes.js'
|
|
9
|
-
import {
|
|
10
|
-
CanCommands,
|
|
11
|
-
ChainedCommands,
|
|
12
|
-
ExtendedRegExpMatchArray,
|
|
13
|
-
Range,
|
|
14
|
-
SingleCommands,
|
|
15
|
-
} from './types.js'
|
|
9
|
+
import { CanCommands, ChainedCommands, ExtendedRegExpMatchArray, Range, SingleCommands } from './types.js'
|
|
16
10
|
import { isRegExp } from './utilities/isRegExp.js'
|
|
17
11
|
|
|
18
12
|
export type InputRuleMatch = {
|
|
19
|
-
index: number
|
|
20
|
-
text: string
|
|
21
|
-
replaceWith?: string
|
|
22
|
-
match?: RegExpMatchArray
|
|
23
|
-
data?: Record<string, any
|
|
24
|
-
}
|
|
13
|
+
index: number
|
|
14
|
+
text: string
|
|
15
|
+
replaceWith?: string
|
|
16
|
+
match?: RegExpMatchArray
|
|
17
|
+
data?: Record<string, any>
|
|
18
|
+
}
|
|
25
19
|
|
|
26
|
-
export type InputRuleFinder = RegExp | ((text: string) => InputRuleMatch | null)
|
|
20
|
+
export type InputRuleFinder = RegExp | ((text: string) => InputRuleMatch | null)
|
|
27
21
|
|
|
28
22
|
export class InputRule {
|
|
29
23
|
find: InputRuleFinder
|
|
30
24
|
|
|
31
25
|
handler: (props: {
|
|
32
|
-
state: EditorState
|
|
33
|
-
range: Range
|
|
34
|
-
match: ExtendedRegExpMatchArray
|
|
35
|
-
commands: SingleCommands
|
|
36
|
-
chain: () => ChainedCommands
|
|
37
|
-
can: () => CanCommands
|
|
26
|
+
state: EditorState
|
|
27
|
+
range: Range
|
|
28
|
+
match: ExtendedRegExpMatchArray
|
|
29
|
+
commands: SingleCommands
|
|
30
|
+
chain: () => ChainedCommands
|
|
31
|
+
can: () => CanCommands
|
|
38
32
|
}) => void | null
|
|
39
33
|
|
|
40
34
|
constructor(config: {
|
|
41
|
-
find: InputRuleFinder
|
|
35
|
+
find: InputRuleFinder
|
|
42
36
|
handler: (props: {
|
|
43
|
-
state: EditorState
|
|
44
|
-
range: Range
|
|
45
|
-
match: ExtendedRegExpMatchArray
|
|
46
|
-
commands: SingleCommands
|
|
47
|
-
chain: () => ChainedCommands
|
|
48
|
-
can: () => CanCommands
|
|
49
|
-
}) => void | null
|
|
37
|
+
state: EditorState
|
|
38
|
+
range: Range
|
|
39
|
+
match: ExtendedRegExpMatchArray
|
|
40
|
+
commands: SingleCommands
|
|
41
|
+
chain: () => ChainedCommands
|
|
42
|
+
can: () => CanCommands
|
|
43
|
+
}) => void | null
|
|
50
44
|
}) {
|
|
51
45
|
this.find = config.find
|
|
52
46
|
this.handler = config.handler
|
|
53
47
|
}
|
|
54
48
|
}
|
|
55
49
|
|
|
56
|
-
const inputRuleMatcherHandler = (
|
|
57
|
-
text: string,
|
|
58
|
-
find: InputRuleFinder,
|
|
59
|
-
): ExtendedRegExpMatchArray | null => {
|
|
50
|
+
const inputRuleMatcherHandler = (text: string, find: InputRuleFinder): ExtendedRegExpMatchArray | null => {
|
|
60
51
|
if (isRegExp(find)) {
|
|
61
52
|
return find.exec(text)
|
|
62
53
|
}
|
|
@@ -75,9 +66,7 @@ const inputRuleMatcherHandler = (
|
|
|
75
66
|
|
|
76
67
|
if (inputRuleMatch.replaceWith) {
|
|
77
68
|
if (!inputRuleMatch.text.includes(inputRuleMatch.replaceWith)) {
|
|
78
|
-
console.warn(
|
|
79
|
-
'[tiptap warn]: "inputRuleMatch.replaceWith" must be part of "inputRuleMatch.text".',
|
|
80
|
-
)
|
|
69
|
+
console.warn('[tiptap warn]: "inputRuleMatch.replaceWith" must be part of "inputRuleMatch.text".')
|
|
81
70
|
}
|
|
82
71
|
|
|
83
72
|
result.push(inputRuleMatch.replaceWith)
|
|
@@ -87,16 +76,14 @@ const inputRuleMatcherHandler = (
|
|
|
87
76
|
}
|
|
88
77
|
|
|
89
78
|
function run(config: {
|
|
90
|
-
editor: Editor
|
|
91
|
-
from: number
|
|
92
|
-
to: number
|
|
93
|
-
text: string
|
|
94
|
-
rules: InputRule[]
|
|
95
|
-
plugin: Plugin
|
|
79
|
+
editor: Editor
|
|
80
|
+
from: number
|
|
81
|
+
to: number
|
|
82
|
+
text: string
|
|
83
|
+
rules: InputRule[]
|
|
84
|
+
plugin: Plugin
|
|
96
85
|
}): boolean {
|
|
97
|
-
const {
|
|
98
|
-
editor, from, to, text, rules, plugin,
|
|
99
|
-
} = config
|
|
86
|
+
const { editor, from, to, text, rules, plugin } = config
|
|
100
87
|
const { view } = editor
|
|
101
88
|
|
|
102
89
|
if (view.composing) {
|
|
@@ -107,9 +94,9 @@ function run(config: {
|
|
|
107
94
|
|
|
108
95
|
if (
|
|
109
96
|
// check for code node
|
|
110
|
-
$from.parent.type.spec.code
|
|
97
|
+
$from.parent.type.spec.code ||
|
|
111
98
|
// check for code mark
|
|
112
|
-
|
|
99
|
+
!!($from.nodeBefore || $from.nodeAfter)?.marks.find(mark => mark.type.spec.code)
|
|
113
100
|
) {
|
|
114
101
|
return false
|
|
115
102
|
}
|
|
@@ -197,8 +184,8 @@ export function inputRulesPlugin(props: { editor: Editor; rules: InputRule[] }):
|
|
|
197
184
|
const simulatedInputMeta = tr.getMeta('applyInputRules') as
|
|
198
185
|
| undefined
|
|
199
186
|
| {
|
|
200
|
-
from: number
|
|
201
|
-
text: string | ProseMirrorNode | Fragment
|
|
187
|
+
from: number
|
|
188
|
+
text: string | ProseMirrorNode | Fragment
|
|
202
189
|
}
|
|
203
190
|
const isSimulatedInput = !!simulatedInputMeta
|
|
204
191
|
|