@tiptap/core 2.1.0-rc.12 → 2.1.0-rc.13
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 +336 -78
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +323 -75
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +336 -78
- package/dist/index.umd.js.map +1 -1
- package/dist/packages/core/src/commands/index.d.ts +2 -0
- package/dist/packages/core/src/commands/joinItemBackward.d.ts +12 -0
- package/dist/packages/core/src/commands/joinItemForward.d.ts +12 -0
- package/dist/packages/core/src/helpers/index.d.ts +1 -0
- package/dist/packages/core/src/helpers/isAtEndOfNode.d.ts +1 -1
- package/dist/packages/core/src/inputRules/nodeInputRule.d.ts +20 -0
- package/dist/packages/core/src/utilities/createStyleTag.d.ts +1 -1
- package/dist/packages/extension-list-keymap/src/listHelpers/findListItemPos.d.ts +6 -0
- package/dist/packages/extension-list-keymap/src/listHelpers/getNextListDepth.d.ts +2 -0
- package/dist/packages/extension-list-keymap/src/listHelpers/handleBackspace.d.ts +2 -0
- package/dist/packages/extension-list-keymap/src/listHelpers/handleDelete.d.ts +2 -0
- package/dist/packages/extension-list-keymap/src/listHelpers/hasListBefore.d.ts +2 -0
- package/dist/packages/extension-list-keymap/src/listHelpers/hasListItemAfter.d.ts +2 -0
- package/dist/packages/extension-list-keymap/src/listHelpers/hasListItemBefore.d.ts +2 -0
- package/dist/packages/extension-list-keymap/src/listHelpers/index.d.ts +10 -0
- package/dist/packages/extension-list-keymap/src/listHelpers/listItemHasSubList.d.ts +3 -0
- package/dist/packages/extension-list-keymap/src/listHelpers/nextListIsDeeper.d.ts +2 -0
- package/dist/packages/extension-list-keymap/src/listHelpers/nextListIsHigher.d.ts +2 -0
- package/package.json +2 -2
- package/src/commands/cut.ts +11 -9
- package/src/commands/index.ts +2 -0
- package/src/commands/joinItemBackward.ts +36 -0
- package/src/commands/joinItemForward.ts +38 -0
- package/src/extensions/keymap.ts +2 -0
- package/src/helpers/index.ts +1 -0
- package/src/helpers/isAtEndOfNode.ts +20 -2
- package/src/inputRules/nodeInputRule.ts +49 -3
- package/src/utilities/createStyleTag.ts +3 -3
|
@@ -17,6 +17,8 @@ export * from './forEach.js';
|
|
|
17
17
|
export * from './insertContent.js';
|
|
18
18
|
export * from './insertContentAt.js';
|
|
19
19
|
export * from './join.js';
|
|
20
|
+
export * from './joinItemBackward.js';
|
|
21
|
+
export * from './joinItemForward.js';
|
|
20
22
|
export * from './keyboardShortcut.js';
|
|
21
23
|
export * from './lift.js';
|
|
22
24
|
export * from './liftEmptyBlock.js';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { RawCommands } from '../types.js';
|
|
2
|
+
declare module '@tiptap/core' {
|
|
3
|
+
interface Commands<ReturnType> {
|
|
4
|
+
joinItemBackward: {
|
|
5
|
+
/**
|
|
6
|
+
* Join two nodes Forwards.
|
|
7
|
+
*/
|
|
8
|
+
joinItemBackward: () => ReturnType;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export declare const joinItemBackward: RawCommands['joinItemBackward'];
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { RawCommands } from '../types.js';
|
|
2
|
+
declare module '@tiptap/core' {
|
|
3
|
+
interface Commands<ReturnType> {
|
|
4
|
+
joinItemForward: {
|
|
5
|
+
/**
|
|
6
|
+
* Join two nodes Forwards.
|
|
7
|
+
*/
|
|
8
|
+
joinItemForward: () => ReturnType;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export declare const joinItemForward: RawCommands['joinItemForward'];
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { EditorState } from '@tiptap/pm/state';
|
|
2
|
-
export declare const
|
|
2
|
+
export declare const isAtEndOfNode: (state: EditorState, nodeType?: string) => boolean;
|
|
@@ -6,7 +6,27 @@ import { ExtendedRegExpMatchArray } from '../types.js';
|
|
|
6
6
|
* matched text is typed into it.
|
|
7
7
|
*/
|
|
8
8
|
export declare function nodeInputRule(config: {
|
|
9
|
+
/**
|
|
10
|
+
* The regex to match.
|
|
11
|
+
*/
|
|
9
12
|
find: InputRuleFinder;
|
|
13
|
+
/**
|
|
14
|
+
* The node type to add.
|
|
15
|
+
*/
|
|
10
16
|
type: NodeType;
|
|
17
|
+
/**
|
|
18
|
+
* Should the input rule replace the node or append to it
|
|
19
|
+
* If true, the node will be replaced
|
|
20
|
+
*/
|
|
21
|
+
blockReplace?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Insert empty paragraph after inserting the node
|
|
24
|
+
* Only works if blockReplace is true
|
|
25
|
+
*/
|
|
26
|
+
addExtraNewline?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* A function that returns the attributes for the node
|
|
29
|
+
* can also be an object of attributes
|
|
30
|
+
*/
|
|
11
31
|
getAttributes?: Record<string, any> | ((match: ExtendedRegExpMatchArray) => Record<string, any>) | false | null;
|
|
12
32
|
}): InputRule;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function createStyleTag(style: string, nonce?: string): HTMLStyleElement;
|
|
1
|
+
export declare function createStyleTag(style: string, nonce?: string, suffix?: string): HTMLStyleElement;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './findListItemPos.js';
|
|
2
|
+
export * from './getNextListDepth.js';
|
|
3
|
+
export * from './handleBackspace.js';
|
|
4
|
+
export * from './handleDelete.js';
|
|
5
|
+
export * from './hasListBefore.js';
|
|
6
|
+
export * from './hasListItemAfter.js';
|
|
7
|
+
export * from './hasListItemBefore.js';
|
|
8
|
+
export * from './listItemHasSubList.js';
|
|
9
|
+
export * from './nextListIsDeeper.js';
|
|
10
|
+
export * from './nextListIsHigher.js';
|
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.1.0-rc.
|
|
4
|
+
"version": "2.1.0-rc.13",
|
|
5
5
|
"homepage": "https://tiptap.dev",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"tiptap",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"dist"
|
|
33
33
|
],
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@tiptap/pm": "^2.1.0-rc.
|
|
35
|
+
"@tiptap/pm": "^2.1.0-rc.13"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"@tiptap/pm": "^2.0.0"
|
package/src/commands/cut.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { TextSelection } from '@tiptap/pm/state'
|
|
2
|
+
|
|
1
3
|
import { RawCommands } from '../types.js'
|
|
2
4
|
|
|
3
5
|
declare module '@tiptap/core' {
|
|
@@ -11,17 +13,17 @@ declare module '@tiptap/core' {
|
|
|
11
13
|
}
|
|
12
14
|
}
|
|
13
15
|
|
|
14
|
-
export const cut: RawCommands['cut'] = (originRange, targetPos) => ({ editor }) => {
|
|
16
|
+
export const cut: RawCommands['cut'] = (originRange, targetPos) => ({ editor, tr }) => {
|
|
15
17
|
const { state } = editor
|
|
16
18
|
|
|
17
19
|
const contentSlice = state.doc.slice(originRange.from, originRange.to)
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
tr.deleteRange(originRange.from, originRange.to)
|
|
22
|
+
const newPos = tr.mapping.map(targetPos)
|
|
23
|
+
|
|
24
|
+
tr.insert(newPos, contentSlice.content)
|
|
25
|
+
|
|
26
|
+
tr.setSelection(new TextSelection(tr.doc.resolve(newPos - 1)))
|
|
27
|
+
|
|
28
|
+
return true
|
|
27
29
|
}
|
package/src/commands/index.ts
CHANGED
|
@@ -17,6 +17,8 @@ export * from './forEach.js'
|
|
|
17
17
|
export * from './insertContent.js'
|
|
18
18
|
export * from './insertContentAt.js'
|
|
19
19
|
export * from './join.js'
|
|
20
|
+
export * from './joinItemBackward.js'
|
|
21
|
+
export * from './joinItemForward.js'
|
|
20
22
|
export * from './keyboardShortcut.js'
|
|
21
23
|
export * from './lift.js'
|
|
22
24
|
export * from './liftEmptyBlock.js'
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { joinPoint } from '@tiptap/pm/transform'
|
|
2
|
+
|
|
3
|
+
import { RawCommands } from '../types.js'
|
|
4
|
+
|
|
5
|
+
declare module '@tiptap/core' {
|
|
6
|
+
interface Commands<ReturnType> {
|
|
7
|
+
joinItemBackward: {
|
|
8
|
+
/**
|
|
9
|
+
* Join two nodes Forwards.
|
|
10
|
+
*/
|
|
11
|
+
joinItemBackward: () => ReturnType
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const joinItemBackward: RawCommands['joinItemBackward'] = () => ({
|
|
17
|
+
tr, state, dispatch,
|
|
18
|
+
}) => {
|
|
19
|
+
try {
|
|
20
|
+
const point = joinPoint(state.doc, state.selection.$from.pos, -1)
|
|
21
|
+
|
|
22
|
+
if (point === null || point === undefined) {
|
|
23
|
+
return false
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
tr.join(point, 2)
|
|
27
|
+
|
|
28
|
+
if (dispatch) {
|
|
29
|
+
dispatch(tr)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return true
|
|
33
|
+
} catch {
|
|
34
|
+
return false
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { joinPoint } from '@tiptap/pm/transform'
|
|
2
|
+
|
|
3
|
+
import { RawCommands } from '../types.js'
|
|
4
|
+
|
|
5
|
+
declare module '@tiptap/core' {
|
|
6
|
+
interface Commands<ReturnType> {
|
|
7
|
+
joinItemForward: {
|
|
8
|
+
/**
|
|
9
|
+
* Join two nodes Forwards.
|
|
10
|
+
*/
|
|
11
|
+
joinItemForward: () => ReturnType
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const joinItemForward: RawCommands['joinItemForward'] = () => ({
|
|
17
|
+
state,
|
|
18
|
+
dispatch,
|
|
19
|
+
tr,
|
|
20
|
+
}) => {
|
|
21
|
+
try {
|
|
22
|
+
const point = joinPoint(state.doc, state.selection.$from.pos, +1)
|
|
23
|
+
|
|
24
|
+
if (point === null || point === undefined) {
|
|
25
|
+
return false
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
tr.join(point, 2)
|
|
29
|
+
|
|
30
|
+
if (dispatch) {
|
|
31
|
+
dispatch(tr)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return true
|
|
35
|
+
} catch (e) {
|
|
36
|
+
return false
|
|
37
|
+
}
|
|
38
|
+
}
|
package/src/extensions/keymap.ts
CHANGED
|
@@ -12,6 +12,7 @@ export const Keymap = Extension.create({
|
|
|
12
12
|
addKeyboardShortcuts() {
|
|
13
13
|
const handleBackspace = () => this.editor.commands.first(({ commands }) => [
|
|
14
14
|
() => commands.undoInputRule(),
|
|
15
|
+
|
|
15
16
|
// maybe convert first text block node to default node
|
|
16
17
|
() => commands.command(({ tr }) => {
|
|
17
18
|
const { selection, doc } = tr
|
|
@@ -32,6 +33,7 @@ export const Keymap = Extension.create({
|
|
|
32
33
|
|
|
33
34
|
return commands.clearNodes()
|
|
34
35
|
}),
|
|
36
|
+
|
|
35
37
|
() => commands.deleteSelection(),
|
|
36
38
|
() => commands.joinBackward(),
|
|
37
39
|
() => commands.selectNodeBackward(),
|
package/src/helpers/index.ts
CHANGED
|
@@ -1,7 +1,25 @@
|
|
|
1
1
|
import { EditorState } from '@tiptap/pm/state'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import { findParentNode } from './findParentNode.js'
|
|
4
|
+
|
|
5
|
+
export const isAtEndOfNode = (state: EditorState, nodeType?: string) => {
|
|
6
|
+
const { $from, $to, $anchor } = state.selection
|
|
7
|
+
|
|
8
|
+
if (nodeType) {
|
|
9
|
+
const parentNode = findParentNode(node => node.type.name === nodeType)(state.selection)
|
|
10
|
+
|
|
11
|
+
if (!parentNode) {
|
|
12
|
+
return false
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const $parentPos = state.doc.resolve(parentNode.pos + 1)
|
|
16
|
+
|
|
17
|
+
if ($anchor.pos + 1 === $parentPos.end()) {
|
|
18
|
+
return true
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return false
|
|
22
|
+
}
|
|
5
23
|
|
|
6
24
|
if ($to.parentOffset < $to.parent.nodeSize - 2 || $from.pos !== $to.pos) {
|
|
7
25
|
return false
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { NodeType } from '@tiptap/pm/model'
|
|
2
|
+
import { TextSelection } from '@tiptap/pm/state'
|
|
2
3
|
|
|
3
4
|
import { InputRule, InputRuleFinder } from '../InputRule.js'
|
|
4
5
|
import { ExtendedRegExpMatchArray } from '../types.js'
|
|
@@ -9,8 +10,32 @@ import { callOrReturn } from '../utilities/callOrReturn.js'
|
|
|
9
10
|
* matched text is typed into it.
|
|
10
11
|
*/
|
|
11
12
|
export function nodeInputRule(config: {
|
|
13
|
+
/**
|
|
14
|
+
* The regex to match.
|
|
15
|
+
*/
|
|
12
16
|
find: InputRuleFinder
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The node type to add.
|
|
20
|
+
*/
|
|
13
21
|
type: NodeType
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Should the input rule replace the node or append to it
|
|
25
|
+
* If true, the node will be replaced
|
|
26
|
+
*/
|
|
27
|
+
blockReplace?: boolean
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Insert empty paragraph after inserting the node
|
|
31
|
+
* Only works if blockReplace is true
|
|
32
|
+
*/
|
|
33
|
+
addExtraNewline?: boolean
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* A function that returns the attributes for the node
|
|
37
|
+
* can also be an object of attributes
|
|
38
|
+
*/
|
|
14
39
|
getAttributes?:
|
|
15
40
|
| Record<string, any>
|
|
16
41
|
| ((match: ExtendedRegExpMatchArray) => Record<string, any>)
|
|
@@ -22,9 +47,11 @@ export function nodeInputRule(config: {
|
|
|
22
47
|
handler: ({ state, range, match }) => {
|
|
23
48
|
const attributes = callOrReturn(config.getAttributes, undefined, match) || {}
|
|
24
49
|
const { tr } = state
|
|
25
|
-
const start = range.from
|
|
50
|
+
const start = config.blockReplace ? range.from - 1 : range.from
|
|
26
51
|
let end = range.to
|
|
27
52
|
|
|
53
|
+
const newNode = config.type.create(attributes)
|
|
54
|
+
|
|
28
55
|
if (match[1]) {
|
|
29
56
|
const offset = match[0].lastIndexOf(match[1])
|
|
30
57
|
let matchStart = start + offset
|
|
@@ -41,9 +68,28 @@ export function nodeInputRule(config: {
|
|
|
41
68
|
tr.insertText(lastChar, start + match[0].length - 1)
|
|
42
69
|
|
|
43
70
|
// insert node from input rule
|
|
44
|
-
tr.replaceWith(matchStart, end,
|
|
71
|
+
tr.replaceWith(matchStart, end, newNode)
|
|
45
72
|
} else if (match[0]) {
|
|
46
|
-
tr.replaceWith(start, end,
|
|
73
|
+
tr.replaceWith(start, end, newNode)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (config.blockReplace && config.addExtraNewline) {
|
|
77
|
+
const { $to } = tr.selection
|
|
78
|
+
const posAfter = $to.end()
|
|
79
|
+
|
|
80
|
+
if ($to.nodeAfter) {
|
|
81
|
+
tr.setSelection(TextSelection.create(tr.doc, $to.pos))
|
|
82
|
+
} else {
|
|
83
|
+
// add node after horizontal rule if it’s the end of the document
|
|
84
|
+
const node = $to.parent.type.contentMatch.defaultType?.create()
|
|
85
|
+
|
|
86
|
+
if (node) {
|
|
87
|
+
tr.insert(posAfter, node)
|
|
88
|
+
tr.setSelection(TextSelection.create(tr.doc, posAfter))
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
tr.scrollIntoView()
|
|
47
93
|
}
|
|
48
94
|
},
|
|
49
95
|
})
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export function createStyleTag(style: string, nonce?: string): HTMLStyleElement {
|
|
2
|
-
const tiptapStyleTag = (<HTMLStyleElement>document.querySelector(
|
|
1
|
+
export function createStyleTag(style: string, nonce?: string, suffix?: string): HTMLStyleElement {
|
|
2
|
+
const tiptapStyleTag = (<HTMLStyleElement>document.querySelector(`style[data-tiptap-style${suffix ? `-${suffix}` : ''}]`))
|
|
3
3
|
|
|
4
4
|
if (tiptapStyleTag !== null) {
|
|
5
5
|
return tiptapStyleTag
|
|
@@ -11,7 +11,7 @@ export function createStyleTag(style: string, nonce?: string): HTMLStyleElement
|
|
|
11
11
|
styleNode.setAttribute('nonce', nonce)
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
styleNode.setAttribute(
|
|
14
|
+
styleNode.setAttribute(`data-tiptap-style${suffix ? `-${suffix}` : ''}`, '')
|
|
15
15
|
styleNode.innerHTML = style
|
|
16
16
|
document.getElementsByTagName('head')[0].appendChild(styleNode)
|
|
17
17
|
|