@tiptap/core 3.4.4 → 3.4.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/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.4",
4
+ "version": "3.4.6",
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.4.4"
55
+ "@tiptap/pm": "^3.4.6"
56
56
  },
57
57
  "peerDependencies": {
58
- "@tiptap/pm": "^3.4.4"
58
+ "@tiptap/pm": "^3.4.6"
59
59
  },
60
60
  "repository": {
61
61
  "type": "git",
package/src/Editor.ts CHANGED
@@ -160,6 +160,10 @@ export class Editor extends EventEmitter<EditorEvents> {
160
160
  this.createView(el)
161
161
  this.emit('mount', { editor: this })
162
162
 
163
+ if (this.css && !document.head.contains(this.css)) {
164
+ document.head.appendChild(this.css)
165
+ }
166
+
163
167
  window.setTimeout(() => {
164
168
  if (this.isDestroyed) {
165
169
  return
@@ -87,89 +87,87 @@ export class ExtensionManager {
87
87
  // based on the `priority` option.
88
88
  const extensions = sortExtensions([...this.extensions].reverse())
89
89
 
90
- const allPlugins = extensions
91
- .map(extension => {
92
- const context = {
93
- name: extension.name,
94
- options: extension.options,
95
- storage: this.editor.extensionStorage[extension.name as keyof Storage],
96
- editor,
97
- type: getSchemaTypeByName(extension.name, this.schema),
98
- }
90
+ const allPlugins = extensions.flatMap(extension => {
91
+ const context = {
92
+ name: extension.name,
93
+ options: extension.options,
94
+ storage: this.editor.extensionStorage[extension.name as keyof Storage],
95
+ editor,
96
+ type: getSchemaTypeByName(extension.name, this.schema),
97
+ }
99
98
 
100
- const plugins: Plugin[] = []
99
+ const plugins: Plugin[] = []
101
100
 
102
- const addKeyboardShortcuts = getExtensionField<AnyConfig['addKeyboardShortcuts']>(
103
- extension,
104
- 'addKeyboardShortcuts',
105
- context,
106
- )
101
+ const addKeyboardShortcuts = getExtensionField<AnyConfig['addKeyboardShortcuts']>(
102
+ extension,
103
+ 'addKeyboardShortcuts',
104
+ context,
105
+ )
107
106
 
108
- let defaultBindings: Record<string, () => boolean> = {}
107
+ let defaultBindings: Record<string, () => boolean> = {}
109
108
 
110
- // bind exit handling
111
- if (extension.type === 'mark' && getExtensionField<MarkConfig['exitable']>(extension, 'exitable', context)) {
112
- defaultBindings.ArrowRight = () => Mark.handleExit({ editor, mark: extension as Mark })
113
- }
109
+ // bind exit handling
110
+ if (extension.type === 'mark' && getExtensionField<MarkConfig['exitable']>(extension, 'exitable', context)) {
111
+ defaultBindings.ArrowRight = () => Mark.handleExit({ editor, mark: extension as Mark })
112
+ }
114
113
 
115
- if (addKeyboardShortcuts) {
116
- const bindings = Object.fromEntries(
117
- Object.entries(addKeyboardShortcuts()).map(([shortcut, method]) => {
118
- return [shortcut, () => method({ editor })]
119
- }),
120
- )
114
+ if (addKeyboardShortcuts) {
115
+ const bindings = Object.fromEntries(
116
+ Object.entries(addKeyboardShortcuts()).map(([shortcut, method]) => {
117
+ return [shortcut, () => method({ editor })]
118
+ }),
119
+ )
121
120
 
122
- defaultBindings = { ...defaultBindings, ...bindings }
123
- }
121
+ defaultBindings = { ...defaultBindings, ...bindings }
122
+ }
124
123
 
125
- const keyMapPlugin = keymap(defaultBindings)
124
+ const keyMapPlugin = keymap(defaultBindings)
126
125
 
127
- plugins.push(keyMapPlugin)
126
+ plugins.push(keyMapPlugin)
128
127
 
129
- const addInputRules = getExtensionField<AnyConfig['addInputRules']>(extension, 'addInputRules', context)
128
+ const addInputRules = getExtensionField<AnyConfig['addInputRules']>(extension, 'addInputRules', context)
130
129
 
131
- if (isExtensionRulesEnabled(extension, editor.options.enableInputRules) && addInputRules) {
132
- const rules = addInputRules()
130
+ if (isExtensionRulesEnabled(extension, editor.options.enableInputRules) && addInputRules) {
131
+ const rules = addInputRules()
133
132
 
134
- if (rules && rules.length) {
135
- const inputResult = inputRulesPlugin({
136
- editor,
137
- rules,
138
- })
133
+ if (rules && rules.length) {
134
+ const inputResult = inputRulesPlugin({
135
+ editor,
136
+ rules,
137
+ })
139
138
 
140
- const inputPlugins = Array.isArray(inputResult) ? inputResult : [inputResult]
139
+ const inputPlugins = Array.isArray(inputResult) ? inputResult : [inputResult]
141
140
 
142
- plugins.push(...inputPlugins)
143
- }
141
+ plugins.push(...inputPlugins)
144
142
  }
143
+ }
145
144
 
146
- const addPasteRules = getExtensionField<AnyConfig['addPasteRules']>(extension, 'addPasteRules', context)
145
+ const addPasteRules = getExtensionField<AnyConfig['addPasteRules']>(extension, 'addPasteRules', context)
147
146
 
148
- if (isExtensionRulesEnabled(extension, editor.options.enablePasteRules) && addPasteRules) {
149
- const rules = addPasteRules()
147
+ if (isExtensionRulesEnabled(extension, editor.options.enablePasteRules) && addPasteRules) {
148
+ const rules = addPasteRules()
150
149
 
151
- if (rules && rules.length) {
152
- const pasteRules = pasteRulesPlugin({ editor, rules })
150
+ if (rules && rules.length) {
151
+ const pasteRules = pasteRulesPlugin({ editor, rules })
153
152
 
154
- plugins.push(...pasteRules)
155
- }
153
+ plugins.push(...pasteRules)
156
154
  }
155
+ }
157
156
 
158
- const addProseMirrorPlugins = getExtensionField<AnyConfig['addProseMirrorPlugins']>(
159
- extension,
160
- 'addProseMirrorPlugins',
161
- context,
162
- )
157
+ const addProseMirrorPlugins = getExtensionField<AnyConfig['addProseMirrorPlugins']>(
158
+ extension,
159
+ 'addProseMirrorPlugins',
160
+ context,
161
+ )
163
162
 
164
- if (addProseMirrorPlugins) {
165
- const proseMirrorPlugins = addProseMirrorPlugins()
163
+ if (addProseMirrorPlugins) {
164
+ const proseMirrorPlugins = addProseMirrorPlugins()
166
165
 
167
- plugins.push(...proseMirrorPlugins)
168
- }
166
+ plugins.push(...proseMirrorPlugins)
167
+ }
169
168
 
170
- return plugins
171
- })
172
- .flat()
169
+ return plugins
170
+ })
173
171
 
174
172
  return allPlugins
175
173
  }
package/src/InputRule.ts CHANGED
@@ -33,6 +33,8 @@ export class InputRule {
33
33
  can: () => CanCommands
34
34
  }) => void | null
35
35
 
36
+ undoable: boolean
37
+
36
38
  constructor(config: {
37
39
  find: InputRuleFinder
38
40
  handler: (props: {
@@ -43,9 +45,11 @@ export class InputRule {
43
45
  chain: () => ChainedCommands
44
46
  can: () => CanCommands
45
47
  }) => void | null
48
+ undoable?: boolean
46
49
  }) {
47
50
  this.find = config.find
48
51
  this.handler = config.handler
52
+ this.undoable = config.undoable ?? true
49
53
  }
50
54
  }
51
55
 
@@ -149,12 +153,14 @@ function run(config: {
149
153
 
150
154
  // store transform as meta data
151
155
  // so we can undo input rules within the `undoInputRules` command
152
- tr.setMeta(plugin, {
153
- transform: tr,
154
- from,
155
- to,
156
- text,
157
- })
156
+ if (rule.undoable) {
157
+ tr.setMeta(plugin, {
158
+ transform: tr,
159
+ from,
160
+ to,
161
+ text,
162
+ })
163
+ }
158
164
 
159
165
  view.dispatch(tr)
160
166
  matched = true
@@ -14,6 +14,7 @@ import { callOrReturn } from '../utilities/callOrReturn.js'
14
14
  export function markInputRule(config: {
15
15
  find: InputRuleFinder
16
16
  type: MarkType
17
+ undoable?: boolean
17
18
  getAttributes?: Record<string, any> | ((match: ExtendedRegExpMatchArray) => Record<string, any>) | false | null
18
19
  }) {
19
20
  return new InputRule({
@@ -62,5 +63,6 @@ export function markInputRule(config: {
62
63
  tr.removeStoredMark(config.type)
63
64
  }
64
65
  },
66
+ undoable: config.undoable,
65
67
  })
66
68
  }
@@ -21,6 +21,12 @@ export function nodeInputRule(config: {
21
21
  */
22
22
  type: NodeType
23
23
 
24
+ /**
25
+ * Whether the input rule should be undoable
26
+ * when the user presses backspace.
27
+ */
28
+ undoable?: boolean
29
+
24
30
  /**
25
31
  * A function that returns the attributes for the node
26
32
  * can also be an object of attributes
@@ -62,5 +68,6 @@ export function nodeInputRule(config: {
62
68
 
63
69
  tr.scrollIntoView()
64
70
  },
71
+ undoable: config.undoable,
65
72
  })
66
73
  }
@@ -6,7 +6,7 @@ import { InputRule } from '../InputRule.js'
6
6
  * matched text is typed into it.
7
7
  * @see https://tiptap.dev/docs/editor/extensions/custom-extensions/extend-existing#input-rules
8
8
  */
9
- export function textInputRule(config: { find: InputRuleFinder; replace: string }) {
9
+ export function textInputRule(config: { find: InputRuleFinder; replace: string; undoable?: boolean }) {
10
10
  return new InputRule({
11
11
  find: config.find,
12
12
  handler: ({ state, range, match }) => {
@@ -30,5 +30,6 @@ export function textInputRule(config: { find: InputRuleFinder; replace: string }
30
30
 
31
31
  state.tr.insertText(insert, start, end)
32
32
  },
33
+ undoable: config.undoable,
33
34
  })
34
35
  }
@@ -15,6 +15,7 @@ import { callOrReturn } from '../utilities/callOrReturn.js'
15
15
  export function textblockTypeInputRule(config: {
16
16
  find: InputRuleFinder
17
17
  type: NodeType
18
+ undoable?: boolean
18
19
  getAttributes?: Record<string, any> | ((match: ExtendedRegExpMatchArray) => Record<string, any>) | false | null
19
20
  }) {
20
21
  return new InputRule({
@@ -29,5 +30,6 @@ export function textblockTypeInputRule(config: {
29
30
 
30
31
  state.tr.delete(range.from, range.to).setBlockType(range.from, range.from, config.type, attributes)
31
32
  },
33
+ undoable: config.undoable,
32
34
  })
33
35
  }
@@ -28,6 +28,7 @@ export function wrappingInputRule(config: {
28
28
  keepMarks?: boolean
29
29
  keepAttributes?: boolean
30
30
  editor?: Editor
31
+ undoable?: boolean
31
32
  getAttributes?: Record<string, any> | ((match: ExtendedRegExpMatchArray) => Record<string, any>) | false | null
32
33
  joinPredicate?: (match: ExtendedRegExpMatchArray, node: ProseMirrorNode) => boolean
33
34
  }) {
@@ -76,5 +77,6 @@ export function wrappingInputRule(config: {
76
77
  tr.join(range.from - 1)
77
78
  }
78
79
  },
80
+ undoable: config.undoable,
79
81
  })
80
82
  }