@tiptap/core 2.0.0-beta.154 → 2.0.0-beta.158

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": "2.0.0-beta.154",
4
+ "version": "2.0.0-beta.158",
5
5
  "homepage": "https://tiptap.dev",
6
6
  "keywords": [
7
7
  "tiptap",
@@ -29,7 +29,7 @@
29
29
  "@types/prosemirror-model": "^1.13.2",
30
30
  "@types/prosemirror-schema-list": "^1.0.3",
31
31
  "@types/prosemirror-state": "^1.2.8",
32
- "@types/prosemirror-transform": "^1.1.4",
32
+ "@types/prosemirror-transform": "^1.1.5",
33
33
  "@types/prosemirror-view": "^1.19.2",
34
34
  "prosemirror-commands": "^1.1.12",
35
35
  "prosemirror-keymap": "^1.1.5",
@@ -44,5 +44,5 @@
44
44
  "url": "https://github.com/ueberdosis/tiptap",
45
45
  "directory": "packages/core"
46
46
  },
47
- "gitHead": "0e0cdc053f067a5edcf179fbd55063da20806bff"
47
+ "gitHead": "73fc527be900b5bc8ac90894118604693727a7e9"
48
48
  }
@@ -14,6 +14,11 @@ const joinListBackwards = (tr: Transaction, listType: NodeType): boolean => {
14
14
  }
15
15
 
16
16
  const before = tr.doc.resolve(Math.max(0, list.pos - 1)).before(list.depth)
17
+
18
+ if (before === undefined) {
19
+ return true
20
+ }
21
+
17
22
  const nodeBefore = tr.doc.nodeAt(before)
18
23
  const canJoinBackwards = list.node.type === nodeBefore?.type
19
24
  && canJoin(tr.doc, list.pos)
@@ -35,6 +40,11 @@ const joinListForwards = (tr: Transaction, listType: NodeType): boolean => {
35
40
  }
36
41
 
37
42
  const after = tr.doc.resolve(list.start).after(list.depth)
43
+
44
+ if (after === undefined) {
45
+ return true
46
+ }
47
+
38
48
  const nodeAfter = tr.doc.nodeAt(after)
39
49
  const canJoinForwards = list.node.type === nodeAfter?.type
40
50
  && canJoin(tr.doc, after)
@@ -1,3 +1,6 @@
1
+ import { Plugin, PluginKey, Selection } from 'prosemirror-state'
2
+ import { createChainableState } from '../helpers/createChainableState'
3
+ import { CommandManager } from '../CommandManager'
1
4
  import { Extension } from '../Extension'
2
5
 
3
6
  export const Keymap = Extension.create({
@@ -6,6 +9,24 @@ export const Keymap = Extension.create({
6
9
  addKeyboardShortcuts() {
7
10
  const handleBackspace = () => this.editor.commands.first(({ commands }) => [
8
11
  () => commands.undoInputRule(),
12
+ // maybe convert first text block node to default node
13
+ () => commands.command(({ tr }) => {
14
+ const { selection, doc } = tr
15
+ const { empty, $anchor } = selection
16
+ const { pos, parent } = $anchor
17
+ const isAtStart = Selection.atStart(doc).from === pos
18
+
19
+ if (
20
+ !empty
21
+ || !isAtStart
22
+ || !parent.type.isTextblock
23
+ || parent.textContent.length
24
+ ) {
25
+ return false
26
+ }
27
+
28
+ return commands.clearNodes()
29
+ }),
9
30
  () => commands.deleteSelection(),
10
31
  () => commands.joinBackward(),
11
32
  () => commands.selectNodeBackward(),
@@ -33,4 +54,53 @@ export const Keymap = Extension.create({
33
54
  'Mod-a': () => this.editor.commands.selectAll(),
34
55
  }
35
56
  },
57
+
58
+ addProseMirrorPlugins() {
59
+ return [
60
+ // With this plugin we check if the whole document was selected and deleted.
61
+ // In this case we will additionally call `clearNodes()` to convert e.g. a heading
62
+ // to a paragraph if necessary.
63
+ // This is an alternative to ProseMirror's `AllSelection`, which doesn’t work well
64
+ // with many other commands.
65
+ new Plugin({
66
+ key: new PluginKey('clearDocument'),
67
+ appendTransaction: (transactions, oldState, newState) => {
68
+ const docChanges = transactions.some(transaction => transaction.docChanged)
69
+ && !oldState.doc.eq(newState.doc)
70
+
71
+ if (!docChanges) {
72
+ return
73
+ }
74
+
75
+ const { empty, from, to } = oldState.selection
76
+ const allFrom = Selection.atStart(oldState.doc).from
77
+ const allEnd = Selection.atEnd(oldState.doc).to
78
+ const allWasSelected = from === allFrom && to === allEnd
79
+ const isEmpty = newState.doc.textBetween(0, newState.doc.content.size, ' ', ' ').length === 0
80
+
81
+ if (empty || !allWasSelected || !isEmpty) {
82
+ return
83
+ }
84
+
85
+ const tr = newState.tr
86
+ const state = createChainableState({
87
+ state: newState,
88
+ transaction: tr,
89
+ })
90
+ const { commands } = new CommandManager({
91
+ editor: this.editor,
92
+ state,
93
+ })
94
+
95
+ commands.clearNodes()
96
+
97
+ if (!tr.steps.length) {
98
+ return
99
+ }
100
+
101
+ return tr
102
+ },
103
+ }),
104
+ ]
105
+ },
36
106
  })
@@ -9,12 +9,19 @@ interface DebugJSONContent extends JSONContent {
9
9
  export function getDebugJSON(node: ProseMirrorNode, startOffset = 0): DebugJSONContent {
10
10
  const isTopNode = node.type === node.type.schema.topNodeType
11
11
  const increment = isTopNode ? 0 : 1
12
- const from = startOffset // + offset
12
+ const from = startOffset
13
13
  const to = from + node.nodeSize
14
- const marks = node.marks.map(mark => ({
15
- type: mark.type.name,
16
- attrs: { ...mark.attrs },
17
- }))
14
+ const marks = node.marks.map(mark => {
15
+ const output: { type: string, attrs?: Record<string, any> } = {
16
+ type: mark.type.name,
17
+ }
18
+
19
+ if (Object.keys(mark.attrs).length) {
20
+ output.attrs = { ...mark.attrs }
21
+ }
22
+
23
+ return output
24
+ })
18
25
  const attrs = { ...node.attrs }
19
26
  const output: DebugJSONContent = {
20
27
  type: node.type.name,