@tiptap/core 3.2.2 → 3.3.0
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/dist/index.cjs +23 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +23 -18
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/ExtensionManager.ts +20 -18
- package/src/PasteRule.ts +20 -3
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiptap/core",
|
|
3
3
|
"description": "headless rich text editor",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.3.0",
|
|
5
5
|
"homepage": "https://tiptap.dev",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"tiptap",
|
|
@@ -52,10 +52,10 @@
|
|
|
52
52
|
"jsx-dev-runtime"
|
|
53
53
|
],
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@tiptap/pm": "^3.
|
|
55
|
+
"@tiptap/pm": "^3.3.0"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
|
-
"@tiptap/pm": "^3.
|
|
58
|
+
"@tiptap/pm": "^3.3.0"
|
|
59
59
|
},
|
|
60
60
|
"repository": {
|
|
61
61
|
"type": "git",
|
package/src/ExtensionManager.ts
CHANGED
|
@@ -18,10 +18,8 @@ import {
|
|
|
18
18
|
splitExtensions,
|
|
19
19
|
} from './helpers/index.js'
|
|
20
20
|
import { type MarkConfig, type NodeConfig, type Storage, getMarkType, updateMarkViewAttributes } from './index.js'
|
|
21
|
-
import type { InputRule } from './InputRule.js'
|
|
22
21
|
import { inputRulesPlugin } from './InputRule.js'
|
|
23
22
|
import { Mark } from './Mark.js'
|
|
24
|
-
import type { PasteRule } from './PasteRule.js'
|
|
25
23
|
import { pasteRulesPlugin } from './PasteRule.js'
|
|
26
24
|
import type { AnyConfig, Extensions, RawCommands } from './types.js'
|
|
27
25
|
import { callOrReturn } from './utilities/callOrReturn.js'
|
|
@@ -89,9 +87,6 @@ export class ExtensionManager {
|
|
|
89
87
|
// based on the `priority` option.
|
|
90
88
|
const extensions = sortExtensions([...this.extensions].reverse())
|
|
91
89
|
|
|
92
|
-
const inputRules: InputRule[] = []
|
|
93
|
-
const pasteRules: PasteRule[] = []
|
|
94
|
-
|
|
95
90
|
const allPlugins = extensions
|
|
96
91
|
.map(extension => {
|
|
97
92
|
const context = {
|
|
@@ -134,13 +129,30 @@ export class ExtensionManager {
|
|
|
134
129
|
const addInputRules = getExtensionField<AnyConfig['addInputRules']>(extension, 'addInputRules', context)
|
|
135
130
|
|
|
136
131
|
if (isExtensionRulesEnabled(extension, editor.options.enableInputRules) && addInputRules) {
|
|
137
|
-
|
|
132
|
+
const rules = addInputRules()
|
|
133
|
+
|
|
134
|
+
if (rules && rules.length) {
|
|
135
|
+
const inputResult = inputRulesPlugin({
|
|
136
|
+
editor,
|
|
137
|
+
rules,
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
const inputPlugins = Array.isArray(inputResult) ? inputResult : [inputResult]
|
|
141
|
+
|
|
142
|
+
plugins.push(...inputPlugins)
|
|
143
|
+
}
|
|
138
144
|
}
|
|
139
145
|
|
|
140
146
|
const addPasteRules = getExtensionField<AnyConfig['addPasteRules']>(extension, 'addPasteRules', context)
|
|
141
147
|
|
|
142
148
|
if (isExtensionRulesEnabled(extension, editor.options.enablePasteRules) && addPasteRules) {
|
|
143
|
-
|
|
149
|
+
const rules = addPasteRules()
|
|
150
|
+
|
|
151
|
+
if (rules && rules.length) {
|
|
152
|
+
const pasteRules = pasteRulesPlugin({ editor, rules })
|
|
153
|
+
|
|
154
|
+
plugins.push(...pasteRules)
|
|
155
|
+
}
|
|
144
156
|
}
|
|
145
157
|
|
|
146
158
|
const addProseMirrorPlugins = getExtensionField<AnyConfig['addProseMirrorPlugins']>(
|
|
@@ -159,17 +171,7 @@ export class ExtensionManager {
|
|
|
159
171
|
})
|
|
160
172
|
.flat()
|
|
161
173
|
|
|
162
|
-
return
|
|
163
|
-
inputRulesPlugin({
|
|
164
|
-
editor,
|
|
165
|
-
rules: inputRules,
|
|
166
|
-
}),
|
|
167
|
-
...pasteRulesPlugin({
|
|
168
|
-
editor,
|
|
169
|
-
rules: pasteRules,
|
|
170
|
-
}),
|
|
171
|
-
...allPlugins,
|
|
172
|
-
]
|
|
174
|
+
return allPlugins
|
|
173
175
|
}
|
|
174
176
|
|
|
175
177
|
/**
|
package/src/PasteRule.ts
CHANGED
|
@@ -112,13 +112,30 @@ function run(config: {
|
|
|
112
112
|
const handlers: (void | null)[] = []
|
|
113
113
|
|
|
114
114
|
state.doc.nodesBetween(from, to, (node, pos) => {
|
|
115
|
-
|
|
115
|
+
// Skip code blocks and non-textual nodes.
|
|
116
|
+
// Be defensive: `node` may be a Fragment without a `type`. Only text,
|
|
117
|
+
// inline, or textblock nodes are processed by paste rules.
|
|
118
|
+
if (node.type?.spec?.code || !(node.isText || node.isTextblock || node.isInline)) {
|
|
116
119
|
return
|
|
117
120
|
}
|
|
118
121
|
|
|
122
|
+
// For textblock and inline/text nodes, compute the range relative to the node.
|
|
123
|
+
// Prefer `node.nodeSize` when available (some Node shapes expose this),
|
|
124
|
+
// otherwise fall back to `node.content?.size`. Default to 0 if neither exists.
|
|
125
|
+
const contentSize = node.content?.size ?? node.nodeSize ?? 0
|
|
119
126
|
const resolvedFrom = Math.max(from, pos)
|
|
120
|
-
const resolvedTo = Math.min(to, pos +
|
|
121
|
-
|
|
127
|
+
const resolvedTo = Math.min(to, pos + contentSize)
|
|
128
|
+
|
|
129
|
+
// If the resolved range is empty or invalid for this node, skip it. This
|
|
130
|
+
// avoids calling `textBetween` with start > end which can cause internal
|
|
131
|
+
// Fragment/Node traversal to access undefined `nodeSize` values.
|
|
132
|
+
if (resolvedFrom >= resolvedTo) {
|
|
133
|
+
return
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const textToMatch = node.isText
|
|
137
|
+
? node.text || ''
|
|
138
|
+
: node.textBetween(resolvedFrom - pos, resolvedTo - pos, undefined, '\ufffc')
|
|
122
139
|
|
|
123
140
|
const matches = pasteRuleMatcherHandler(textToMatch, rule.find, pasteEvent)
|
|
124
141
|
|