@tiptap/core 2.0.0-beta.164 → 2.0.0-beta.168

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.164",
4
+ "version": "2.0.0-beta.168",
5
5
  "homepage": "https://tiptap.dev",
6
6
  "keywords": [
7
7
  "tiptap",
@@ -30,14 +30,14 @@
30
30
  "@types/prosemirror-schema-list": "^1.0.3",
31
31
  "@types/prosemirror-state": "^1.2.8",
32
32
  "@types/prosemirror-transform": "^1.1.5",
33
- "@types/prosemirror-view": "^1.19.2",
34
- "prosemirror-commands": "^1.1.12",
33
+ "@types/prosemirror-view": "^1.23.1",
34
+ "prosemirror-commands": "^1.2.1",
35
35
  "prosemirror-keymap": "^1.1.5",
36
36
  "prosemirror-model": "^1.16.1",
37
37
  "prosemirror-schema-list": "^1.1.6",
38
38
  "prosemirror-state": "^1.3.4",
39
39
  "prosemirror-transform": "^1.3.3",
40
- "prosemirror-view": "^1.23.5"
40
+ "prosemirror-view": "^1.23.6"
41
41
  },
42
42
  "repository": {
43
43
  "type": "git",
@@ -45,5 +45,5 @@
45
45
  "directory": "packages/core"
46
46
  },
47
47
  "sideEffects": false,
48
- "gitHead": "9e48f8c23960198b166b23804c094f2ddccc3927"
48
+ "gitHead": "31efb0802e77e32c8c1b65e1a8456a5d3262b0ae"
49
49
  }
@@ -15,6 +15,10 @@ export const blur: RawCommands['blur'] = () => ({ editor, view }) => {
15
15
  requestAnimationFrame(() => {
16
16
  if (!editor.isDestroyed) {
17
17
  (view.dom as HTMLElement).blur()
18
+
19
+ // Browsers should remove the caret on blur but safari does not.
20
+ // See: https://github.com/ueberdosis/tiptap/issues/2405
21
+ window?.getSelection()?.removeAllRanges()
18
22
  }
19
23
  })
20
24
 
@@ -53,6 +53,7 @@ export const insertContentAt: RawCommands['insertContentAt'] = (position, value,
53
53
  ? { from: position, to: position }
54
54
  : position
55
55
 
56
+ let isOnlyTextContent = true
56
57
  let isOnlyBlockContent = true
57
58
  const nodes = isFragment(content)
58
59
  ? content
@@ -62,6 +63,10 @@ export const insertContentAt: RawCommands['insertContentAt'] = (position, value,
62
63
  // check if added node is valid
63
64
  node.check()
64
65
 
66
+ isOnlyTextContent = isOnlyTextContent
67
+ ? node.isText && node.marks.length === 0
68
+ : false
69
+
65
70
  isOnlyBlockContent = isOnlyBlockContent
66
71
  ? node.isBlock
67
72
  : false
@@ -84,7 +89,13 @@ export const insertContentAt: RawCommands['insertContentAt'] = (position, value,
84
89
  }
85
90
  }
86
91
 
87
- tr.replaceWith(from, to, content)
92
+ // if there is only plain text we have to use `insertText`
93
+ // because this will keep the current marks
94
+ if (isOnlyTextContent) {
95
+ tr.insertText(value as string, from, to)
96
+ } else {
97
+ tr.replaceWith(from, to, content)
98
+ }
88
99
 
89
100
  // set cursor at end of inserted content
90
101
  if (options.updateSelection) {
@@ -1,6 +1,6 @@
1
1
  import { RawCommands } from '../types'
2
-
3
- const mac = typeof navigator !== 'undefined' ? /Mac/.test(navigator.platform) : false
2
+ import { isiOS } from '../utilities/isiOS'
3
+ import { isMacOS } from '../utilities/isMacOS'
4
4
 
5
5
  function normalizeKeyName(name: string) {
6
6
  const parts = name.split(/-(?!$)/)
@@ -27,7 +27,7 @@ function normalizeKeyName(name: string) {
27
27
  } else if (/^s(hift)?$/i.test(mod)) {
28
28
  shift = true
29
29
  } else if (/^mod$/i.test(mod)) {
30
- if (mac) {
30
+ if (isiOS() || isMacOS()) {
31
31
  meta = true
32
32
  } else {
33
33
  ctrl = true
@@ -0,0 +1,19 @@
1
+ // @ts-ignore
2
+ // TODO: add types to @types/prosemirror-commands
3
+ import { selectTextblockEnd as originalSelectTextblockEnd } from 'prosemirror-commands'
4
+ import { RawCommands } from '../types'
5
+
6
+ declare module '@tiptap/core' {
7
+ interface Commands<ReturnType> {
8
+ selectTextblockEnd: {
9
+ /**
10
+ * Moves the cursor to the end of current text block.
11
+ */
12
+ selectTextblockEnd: () => ReturnType,
13
+ }
14
+ }
15
+ }
16
+
17
+ export const selectTextblockEnd: RawCommands['selectTextblockEnd'] = () => ({ state, dispatch }) => {
18
+ return originalSelectTextblockEnd(state, dispatch)
19
+ }
@@ -0,0 +1,19 @@
1
+ // @ts-ignore
2
+ // TODO: add types to @types/prosemirror-commands
3
+ import { selectTextblockStart as originalSelectTextblockStart } from 'prosemirror-commands'
4
+ import { RawCommands } from '../types'
5
+
6
+ declare module '@tiptap/core' {
7
+ interface Commands<ReturnType> {
8
+ selectTextblockStart: {
9
+ /**
10
+ * Moves the cursor to the start of current text block.
11
+ */
12
+ selectTextblockStart: () => ReturnType,
13
+ }
14
+ }
15
+ }
16
+
17
+ export const selectTextblockStart: RawCommands['selectTextblockStart'] = () => ({ state, dispatch }) => {
18
+ return originalSelectTextblockStart(state, dispatch)
19
+ }
@@ -28,6 +28,8 @@ import * as selectAll from '../commands/selectAll'
28
28
  import * as selectNodeBackward from '../commands/selectNodeBackward'
29
29
  import * as selectNodeForward from '../commands/selectNodeForward'
30
30
  import * as selectParentNode from '../commands/selectParentNode'
31
+ import * as selectTextblockEnd from '../commands/selectTextblockEnd'
32
+ import * as selectTextblockStart from '../commands/selectTextblockStart'
31
33
  import * as setContent from '../commands/setContent'
32
34
  import * as setMark from '../commands/setMark'
33
35
  import * as setMeta from '../commands/setMeta'
@@ -77,6 +79,8 @@ export { selectAll }
77
79
  export { selectNodeBackward }
78
80
  export { selectNodeForward }
79
81
  export { selectParentNode }
82
+ export { selectTextblockEnd }
83
+ export { selectTextblockStart }
80
84
  export { setContent }
81
85
  export { setMark }
82
86
  export { setMeta }
@@ -131,6 +135,8 @@ export const Commands = Extension.create({
131
135
  ...selectNodeBackward,
132
136
  ...selectNodeForward,
133
137
  ...selectParentNode,
138
+ ...selectTextblockEnd,
139
+ ...selectTextblockStart,
134
140
  ...setContent,
135
141
  ...setMark,
136
142
  ...setMeta,
@@ -1,5 +1,7 @@
1
1
  import { Plugin, PluginKey, Selection } from 'prosemirror-state'
2
2
  import { createChainableState } from '../helpers/createChainableState'
3
+ import { isiOS } from '../utilities/isiOS'
4
+ import { isMacOS } from '../utilities/isMacOS'
3
5
  import { CommandManager } from '../CommandManager'
4
6
  import { Extension } from '../Extension'
5
7
 
@@ -38,13 +40,15 @@ export const Keymap = Extension.create({
38
40
  () => commands.selectNodeForward(),
39
41
  ])
40
42
 
41
- return {
42
- Enter: () => this.editor.commands.first(({ commands }) => [
43
- () => commands.newlineInCode(),
44
- () => commands.createParagraphNear(),
45
- () => commands.liftEmptyBlock(),
46
- () => commands.splitBlock(),
47
- ]),
43
+ const handleEnter = () => this.editor.commands.first(({ commands }) => [
44
+ () => commands.newlineInCode(),
45
+ () => commands.createParagraphNear(),
46
+ () => commands.liftEmptyBlock(),
47
+ () => commands.splitBlock(),
48
+ ])
49
+
50
+ const baseKeymap = {
51
+ Enter: handleEnter,
48
52
  'Mod-Enter': () => this.editor.commands.exitCode(),
49
53
  Backspace: handleBackspace,
50
54
  'Mod-Backspace': handleBackspace,
@@ -53,6 +57,30 @@ export const Keymap = Extension.create({
53
57
  'Mod-Delete': handleDelete,
54
58
  'Mod-a': () => this.editor.commands.selectAll(),
55
59
  }
60
+
61
+ const pcKeymap = {
62
+ ...baseKeymap,
63
+ Home: () => this.editor.commands.selectTextblockStart(),
64
+ End: () => this.editor.commands.selectTextblockStart(),
65
+ }
66
+
67
+ const macKeymap = {
68
+ ...baseKeymap,
69
+ 'Ctrl-h': handleBackspace,
70
+ 'Alt-Backspace': handleBackspace,
71
+ 'Ctrl-d': handleDelete,
72
+ 'Ctrl-Alt-Backspace': handleDelete,
73
+ 'Alt-Delete': handleDelete,
74
+ 'Alt-d': handleDelete,
75
+ 'Ctrl-a': () => this.editor.commands.selectTextblockStart(),
76
+ 'Ctrl-e': () => this.editor.commands.selectTextblockEnd(),
77
+ }
78
+
79
+ if (isiOS() || isMacOS()) {
80
+ return macKeymap
81
+ }
82
+
83
+ return pcKeymap
56
84
  },
57
85
 
58
86
  addProseMirrorPlugins() {
@@ -25,26 +25,20 @@ export function injectExtensionAttributesToParseRule(parseRule: ParseRule, exten
25
25
  return false
26
26
  }
27
27
 
28
- const newAttributes = extensionAttributes
29
- .filter(item => item.attribute.rendered)
30
- .reduce((items, item) => {
31
- const value = item.attribute.parseHTML
32
- ? item.attribute.parseHTML(node as HTMLElement)
33
- : fromString((node as HTMLElement).getAttribute(item.name))
34
-
35
- if (isObject(value)) {
36
- console.warn(`[tiptap warn]: BREAKING CHANGE: "parseHTML" for your attribute "${item.name}" returns an object but should return the value itself. If this is expected you can ignore this message. This warning will be removed in one of the next releases. Further information: https://github.com/ueberdosis/tiptap/issues/1863`)
37
- }
38
-
39
- if (value === null || value === undefined) {
40
- return items
41
- }
42
-
43
- return {
44
- ...items,
45
- [item.name]: value,
46
- }
47
- }, {})
28
+ const newAttributes = extensionAttributes.reduce((items, item) => {
29
+ const value = item.attribute.parseHTML
30
+ ? item.attribute.parseHTML(node as HTMLElement)
31
+ : fromString((node as HTMLElement).getAttribute(item.name))
32
+
33
+ if (value === null || value === undefined) {
34
+ return items
35
+ }
36
+
37
+ return {
38
+ ...items,
39
+ [item.name]: value,
40
+ }
41
+ }, {})
48
42
 
49
43
  return { ...oldAttributes, ...newAttributes }
50
44
  },
@@ -0,0 +1,5 @@
1
+ export function isMacOS(): boolean {
2
+ return typeof navigator !== 'undefined'
3
+ ? /Mac/.test(navigator.platform)
4
+ : false
5
+ }