@tiptap/core 2.0.0-beta.217 → 2.0.0-beta.219
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 +90 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +77 -24
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +90 -23
- package/dist/index.umd.js.map +1 -1
- package/dist/packages/core/src/NodeView.d.ts +3 -3
- package/dist/packages/core/src/commands/toggleList.d.ts +1 -1
- package/dist/packages/core/src/helpers/index.d.ts +14 -0
- package/dist/packages/core/src/inputRules/wrappingInputRule.d.ts +4 -0
- package/dist/packages/core/src/pasteRules/nodePasteRule.d.ts +2 -2
- package/dist/packages/core/src/types.d.ts +5 -2
- package/package.json +2 -2
- package/src/Editor.ts +1 -1
- package/src/NodeView.ts +14 -6
- package/src/commands/insertContentAt.ts +9 -1
- package/src/commands/splitListItem.ts +12 -0
- package/src/commands/toggleList.ts +28 -7
- package/src/helpers/createNodeFromContent.ts +1 -1
- package/src/helpers/index.ts +14 -0
- package/src/inputRules/wrappingInputRule.ts +33 -8
- package/src/pasteRules/nodePasteRule.ts +2 -2
- package/src/types.ts +8 -2
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { Node as ProseMirrorNode } from '@tiptap/pm/model';
|
|
2
|
-
import {
|
|
2
|
+
import { NodeView as ProseMirrorNodeView } from '@tiptap/pm/view';
|
|
3
3
|
import { Editor as CoreEditor } from './Editor';
|
|
4
4
|
import { Node } from './Node';
|
|
5
|
-
import { NodeViewRendererOptions, NodeViewRendererProps } from './types';
|
|
5
|
+
import { DecorationWithType, NodeViewRendererOptions, NodeViewRendererProps } from './types';
|
|
6
6
|
export declare class NodeView<Component, NodeEditor extends CoreEditor = CoreEditor, Options extends NodeViewRendererOptions = NodeViewRendererOptions> implements ProseMirrorNodeView {
|
|
7
7
|
component: Component;
|
|
8
8
|
editor: NodeEditor;
|
|
9
9
|
options: Options;
|
|
10
10
|
extension: Node;
|
|
11
11
|
node: ProseMirrorNode;
|
|
12
|
-
decorations:
|
|
12
|
+
decorations: DecorationWithType[];
|
|
13
13
|
getPos: any;
|
|
14
14
|
isDragging: boolean;
|
|
15
15
|
constructor(component: Component, props: NodeViewRendererProps, options?: Partial<Options>);
|
|
@@ -6,7 +6,7 @@ declare module '@tiptap/core' {
|
|
|
6
6
|
/**
|
|
7
7
|
* Toggle between different list types.
|
|
8
8
|
*/
|
|
9
|
-
toggleList: (listTypeOrName: string | NodeType, itemTypeOrName: string | NodeType) => ReturnType;
|
|
9
|
+
toggleList: (listTypeOrName: string | NodeType, itemTypeOrName: string | NodeType, keepMarks?: boolean) => ReturnType;
|
|
10
10
|
};
|
|
11
11
|
}
|
|
12
12
|
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export * from './combineTransactionSteps';
|
|
2
|
+
export * from './createChainableState';
|
|
3
|
+
export * from './createDocument';
|
|
4
|
+
export * from './createNodeFromContent';
|
|
2
5
|
export * from './defaultBlockAt';
|
|
3
6
|
export * from './findChildren';
|
|
4
7
|
export * from './findChildrenInRange';
|
|
@@ -8,6 +11,7 @@ export * from './generateHTML';
|
|
|
8
11
|
export * from './generateJSON';
|
|
9
12
|
export * from './generateText';
|
|
10
13
|
export * from './getAttributes';
|
|
14
|
+
export * from './getAttributesFromExtensions';
|
|
11
15
|
export * from './getChangedRanges';
|
|
12
16
|
export * from './getDebugJSON';
|
|
13
17
|
export * from './getExtensionField';
|
|
@@ -18,12 +22,19 @@ export * from './getMarksBetween';
|
|
|
18
22
|
export * from './getMarkType';
|
|
19
23
|
export * from './getNodeAttributes';
|
|
20
24
|
export * from './getNodeType';
|
|
25
|
+
export * from './getRenderedAttributes';
|
|
21
26
|
export * from './getSchema';
|
|
27
|
+
export * from './getSchemaByResolvedExtensions';
|
|
28
|
+
export * from './getSchemaTypeByName';
|
|
29
|
+
export * from './getSchemaTypeNameByName';
|
|
30
|
+
export * from './getSplittedAttributes';
|
|
22
31
|
export * from './getText';
|
|
23
32
|
export * from './getTextBetween';
|
|
24
33
|
export * from './getTextContentFromNodes';
|
|
25
34
|
export * from './getTextSerializersFromSchema';
|
|
35
|
+
export * from './injectExtensionAttributesToParseRule';
|
|
26
36
|
export * from './isActive';
|
|
37
|
+
export * from './isExtensionRulesEnabled';
|
|
27
38
|
export * from './isList';
|
|
28
39
|
export * from './isMarkActive';
|
|
29
40
|
export * from './isNodeActive';
|
|
@@ -31,3 +42,6 @@ export * from './isNodeEmpty';
|
|
|
31
42
|
export * from './isNodeSelection';
|
|
32
43
|
export * from './isTextSelection';
|
|
33
44
|
export * from './posToDOMRect';
|
|
45
|
+
export * from './resolveFocusPosition';
|
|
46
|
+
export * from './selectionToInsertionEnd';
|
|
47
|
+
export * from './splitExtensions';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Node as ProseMirrorNode, NodeType } from '@tiptap/pm/model';
|
|
2
|
+
import { Editor } from '../Editor';
|
|
2
3
|
import { InputRule, InputRuleFinder } from '../InputRule';
|
|
3
4
|
import { ExtendedRegExpMatchArray } from '../types';
|
|
4
5
|
/**
|
|
@@ -18,6 +19,9 @@ import { ExtendedRegExpMatchArray } from '../types';
|
|
|
18
19
|
export declare function wrappingInputRule(config: {
|
|
19
20
|
find: InputRuleFinder;
|
|
20
21
|
type: NodeType;
|
|
22
|
+
keepMarks?: boolean;
|
|
23
|
+
keepAttributes?: boolean;
|
|
24
|
+
editor?: Editor;
|
|
21
25
|
getAttributes?: Record<string, any> | ((match: ExtendedRegExpMatchArray) => Record<string, any>) | false | null;
|
|
22
26
|
joinPredicate?: (match: ExtendedRegExpMatchArray, node: ProseMirrorNode) => boolean;
|
|
23
27
|
}): InputRule;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { NodeType } from '@tiptap/pm/model';
|
|
2
|
-
import { PasteRule } from '../PasteRule';
|
|
2
|
+
import { PasteRule, PasteRuleFinder } from '../PasteRule';
|
|
3
3
|
import { ExtendedRegExpMatchArray } from '../types';
|
|
4
4
|
/**
|
|
5
5
|
* Build an paste rule that adds a node when the
|
|
6
6
|
* matched text is pasted into it.
|
|
7
7
|
*/
|
|
8
8
|
export declare function nodePasteRule(config: {
|
|
9
|
-
find:
|
|
9
|
+
find: PasteRuleFinder;
|
|
10
10
|
type: NodeType;
|
|
11
11
|
getAttributes?: Record<string, any> | ((match: ExtendedRegExpMatchArray) => Record<string, any>) | false | null;
|
|
12
12
|
}): PasteRule;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Mark as ProseMirrorMark, Node as ProseMirrorNode, ParseOptions } from '@tiptap/pm/model';
|
|
1
|
+
import { Mark as ProseMirrorMark, Node as ProseMirrorNode, NodeType, ParseOptions } from '@tiptap/pm/model';
|
|
2
2
|
import { EditorState, Transaction } from '@tiptap/pm/state';
|
|
3
3
|
import { Decoration, EditorProps, EditorView, NodeView } from '@tiptap/pm/view';
|
|
4
4
|
import { Commands, ExtensionConfig, MarkConfig, NodeConfig } from '.';
|
|
@@ -135,10 +135,13 @@ export declare type ValuesOf<T> = T[keyof T];
|
|
|
135
135
|
export declare type KeysWithTypeOf<T, Type> = {
|
|
136
136
|
[P in keyof T]: T[P] extends Type ? P : never;
|
|
137
137
|
}[keyof T];
|
|
138
|
+
export declare type DecorationWithType = Decoration & {
|
|
139
|
+
type: NodeType;
|
|
140
|
+
};
|
|
138
141
|
export declare type NodeViewProps = {
|
|
139
142
|
editor: Editor;
|
|
140
143
|
node: ProseMirrorNode;
|
|
141
|
-
decorations:
|
|
144
|
+
decorations: DecorationWithType[];
|
|
142
145
|
selected: boolean;
|
|
143
146
|
extension: Node;
|
|
144
147
|
getPos: () => number;
|
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.
|
|
4
|
+
"version": "2.0.0-beta.219",
|
|
5
5
|
"homepage": "https://tiptap.dev",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"tiptap",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"@tiptap/pm": "^2.0.0-beta.209"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@tiptap/pm": "^2.0.0-beta.
|
|
38
|
+
"@tiptap/pm": "^2.0.0-beta.219"
|
|
39
39
|
},
|
|
40
40
|
"repository": {
|
|
41
41
|
"type": "git",
|
package/src/Editor.ts
CHANGED
|
@@ -426,8 +426,8 @@ export class Editor extends EventEmitter<EditorEvents> {
|
|
|
426
426
|
return getText(this.state.doc, {
|
|
427
427
|
blockSeparator,
|
|
428
428
|
textSerializers: {
|
|
429
|
-
...textSerializers,
|
|
430
429
|
...getTextSerializersFromSchema(this.schema),
|
|
430
|
+
...textSerializers,
|
|
431
431
|
},
|
|
432
432
|
})
|
|
433
433
|
}
|
package/src/NodeView.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Node as ProseMirrorNode } from '@tiptap/pm/model'
|
|
2
2
|
import { NodeSelection } from '@tiptap/pm/state'
|
|
3
|
-
import {
|
|
3
|
+
import { NodeView as ProseMirrorNodeView } from '@tiptap/pm/view'
|
|
4
4
|
|
|
5
5
|
import { Editor as CoreEditor } from './Editor'
|
|
6
6
|
import { Node } from './Node'
|
|
7
|
-
import { NodeViewRendererOptions, NodeViewRendererProps } from './types'
|
|
7
|
+
import { DecorationWithType, NodeViewRendererOptions, NodeViewRendererProps } from './types'
|
|
8
8
|
import { isiOS } from './utilities/isiOS'
|
|
9
9
|
|
|
10
10
|
export class NodeView<
|
|
@@ -22,7 +22,7 @@ export class NodeView<
|
|
|
22
22
|
|
|
23
23
|
node: ProseMirrorNode
|
|
24
24
|
|
|
25
|
-
decorations:
|
|
25
|
+
decorations: DecorationWithType[]
|
|
26
26
|
|
|
27
27
|
getPos: any
|
|
28
28
|
|
|
@@ -38,7 +38,7 @@ export class NodeView<
|
|
|
38
38
|
} as Options
|
|
39
39
|
this.extension = props.extension
|
|
40
40
|
this.node = props.node
|
|
41
|
-
this.decorations = props.decorations
|
|
41
|
+
this.decorations = props.decorations as DecorationWithType[]
|
|
42
42
|
this.getPos = props.getPos
|
|
43
43
|
this.mount()
|
|
44
44
|
}
|
|
@@ -113,11 +113,12 @@ export class NodeView<
|
|
|
113
113
|
return false
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
+
const isDragEvent = event.type.startsWith('drag')
|
|
116
117
|
const isDropEvent = event.type === 'drop'
|
|
117
118
|
const isInput = ['INPUT', 'BUTTON', 'SELECT', 'TEXTAREA'].includes(target.tagName) || target.isContentEditable
|
|
118
119
|
|
|
119
120
|
// any input event within node views should be ignored by ProseMirror
|
|
120
|
-
if (isInput && !isDropEvent) {
|
|
121
|
+
if (isInput && !isDropEvent && !isDragEvent) {
|
|
121
122
|
return true
|
|
122
123
|
}
|
|
123
124
|
|
|
@@ -129,7 +130,6 @@ export class NodeView<
|
|
|
129
130
|
const isPasteEvent = event.type === 'paste'
|
|
130
131
|
const isCutEvent = event.type === 'cut'
|
|
131
132
|
const isClickEvent = event.type === 'mousedown'
|
|
132
|
-
const isDragEvent = event.type.startsWith('drag')
|
|
133
133
|
|
|
134
134
|
// ProseMirror tries to drag selectable nodes
|
|
135
135
|
// even if `draggable` is set to `false`
|
|
@@ -159,6 +159,14 @@ export class NodeView<
|
|
|
159
159
|
{ once: true },
|
|
160
160
|
)
|
|
161
161
|
|
|
162
|
+
document.addEventListener(
|
|
163
|
+
'drop',
|
|
164
|
+
() => {
|
|
165
|
+
this.isDragging = false
|
|
166
|
+
},
|
|
167
|
+
{ once: true },
|
|
168
|
+
)
|
|
169
|
+
|
|
162
170
|
document.addEventListener(
|
|
163
171
|
'mouseup',
|
|
164
172
|
() => {
|
|
@@ -79,7 +79,15 @@ export const insertContentAt: RawCommands['insertContentAt'] = (position, value,
|
|
|
79
79
|
// if there is only plain text we have to use `insertText`
|
|
80
80
|
// because this will keep the current marks
|
|
81
81
|
if (isOnlyTextContent) {
|
|
82
|
-
|
|
82
|
+
// if value is string, we can use it directly
|
|
83
|
+
// otherwise if it is an array, we have to join it
|
|
84
|
+
if (Array.isArray(value)) {
|
|
85
|
+
tr.insertText(value.map(v => v.text || '').join(''), from, to)
|
|
86
|
+
} else if (typeof value === 'object' && !!value && !!value.text) {
|
|
87
|
+
tr.insertText(value.text, from, to)
|
|
88
|
+
} else {
|
|
89
|
+
tr.insertText(value as string, from, to)
|
|
90
|
+
}
|
|
83
91
|
} else {
|
|
84
92
|
tr.replaceWith(from, to, content)
|
|
85
93
|
}
|
|
@@ -130,7 +130,19 @@ export const splitListItem: RawCommands['splitListItem'] = typeOrName => ({
|
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
if (dispatch) {
|
|
133
|
+
const { selection, storedMarks } = state
|
|
134
|
+
const { splittableMarks } = editor.extensionManager
|
|
135
|
+
const marks = storedMarks || (selection.$to.parentOffset && selection.$from.marks())
|
|
136
|
+
|
|
133
137
|
tr.split($from.pos, 2, types).scrollIntoView()
|
|
138
|
+
|
|
139
|
+
if (!marks || !dispatch) {
|
|
140
|
+
return true
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const filteredMarks = marks.filter(mark => splittableMarks.includes(mark.type.name))
|
|
144
|
+
|
|
145
|
+
tr.ensureMarks(filteredMarks)
|
|
134
146
|
}
|
|
135
147
|
|
|
136
148
|
return true
|
|
@@ -63,24 +63,23 @@ declare module '@tiptap/core' {
|
|
|
63
63
|
/**
|
|
64
64
|
* Toggle between different list types.
|
|
65
65
|
*/
|
|
66
|
-
toggleList: (
|
|
67
|
-
listTypeOrName: string | NodeType,
|
|
68
|
-
itemTypeOrName: string | NodeType,
|
|
69
|
-
) => ReturnType
|
|
66
|
+
toggleList: (listTypeOrName: string | NodeType, itemTypeOrName: string | NodeType, keepMarks?: boolean) => ReturnType;
|
|
70
67
|
}
|
|
71
68
|
}
|
|
72
69
|
}
|
|
73
70
|
|
|
74
|
-
export const toggleList: RawCommands['toggleList'] = (listTypeOrName, itemTypeOrName) => ({
|
|
71
|
+
export const toggleList: RawCommands['toggleList'] = (listTypeOrName, itemTypeOrName, keepMarks) => ({
|
|
75
72
|
editor, tr, state, dispatch, chain, commands, can,
|
|
76
73
|
}) => {
|
|
77
|
-
const { extensions } = editor.extensionManager
|
|
74
|
+
const { extensions, splittableMarks } = editor.extensionManager
|
|
78
75
|
const listType = getNodeType(listTypeOrName, state.schema)
|
|
79
76
|
const itemType = getNodeType(itemTypeOrName, state.schema)
|
|
80
|
-
const { selection } = state
|
|
77
|
+
const { selection, storedMarks } = state
|
|
81
78
|
const { $from, $to } = selection
|
|
82
79
|
const range = $from.blockRange($to)
|
|
83
80
|
|
|
81
|
+
const marks = storedMarks || (selection.$to.parentOffset && selection.$from.marks())
|
|
82
|
+
|
|
84
83
|
if (!range) {
|
|
85
84
|
return false
|
|
86
85
|
}
|
|
@@ -110,6 +109,24 @@ export const toggleList: RawCommands['toggleList'] = (listTypeOrName, itemTypeOr
|
|
|
110
109
|
.run()
|
|
111
110
|
}
|
|
112
111
|
}
|
|
112
|
+
if (!keepMarks || !marks || !dispatch) {
|
|
113
|
+
|
|
114
|
+
return chain()
|
|
115
|
+
// try to convert node to default node if needed
|
|
116
|
+
.command(() => {
|
|
117
|
+
const canWrapInList = can().wrapInList(listType)
|
|
118
|
+
|
|
119
|
+
if (canWrapInList) {
|
|
120
|
+
return true
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return commands.clearNodes()
|
|
124
|
+
})
|
|
125
|
+
.wrapInList(listType)
|
|
126
|
+
.command(() => joinListBackwards(tr, listType))
|
|
127
|
+
.command(() => joinListForwards(tr, listType))
|
|
128
|
+
.run()
|
|
129
|
+
}
|
|
113
130
|
|
|
114
131
|
return (
|
|
115
132
|
chain()
|
|
@@ -117,6 +134,10 @@ export const toggleList: RawCommands['toggleList'] = (listTypeOrName, itemTypeOr
|
|
|
117
134
|
.command(() => {
|
|
118
135
|
const canWrapInList = can().wrapInList(listType)
|
|
119
136
|
|
|
137
|
+
const filteredMarks = marks.filter(mark => splittableMarks.includes(mark.type.name))
|
|
138
|
+
|
|
139
|
+
tr.ensureMarks(filteredMarks)
|
|
140
|
+
|
|
120
141
|
if (canWrapInList) {
|
|
121
142
|
return true
|
|
122
143
|
}
|
|
@@ -27,7 +27,7 @@ export function createNodeFromContent(
|
|
|
27
27
|
|
|
28
28
|
if (typeof content === 'object' && content !== null) {
|
|
29
29
|
try {
|
|
30
|
-
if (Array.isArray(content)) {
|
|
30
|
+
if (Array.isArray(content) && content.length > 0) {
|
|
31
31
|
return Fragment.fromArray(content.map(item => schema.nodeFromJSON(item)))
|
|
32
32
|
}
|
|
33
33
|
|
package/src/helpers/index.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export * from './combineTransactionSteps'
|
|
2
|
+
export * from './createChainableState'
|
|
3
|
+
export * from './createDocument'
|
|
4
|
+
export * from './createNodeFromContent'
|
|
2
5
|
export * from './defaultBlockAt'
|
|
3
6
|
export * from './findChildren'
|
|
4
7
|
export * from './findChildrenInRange'
|
|
@@ -8,6 +11,7 @@ export * from './generateHTML'
|
|
|
8
11
|
export * from './generateJSON'
|
|
9
12
|
export * from './generateText'
|
|
10
13
|
export * from './getAttributes'
|
|
14
|
+
export * from './getAttributesFromExtensions'
|
|
11
15
|
export * from './getChangedRanges'
|
|
12
16
|
export * from './getDebugJSON'
|
|
13
17
|
export * from './getExtensionField'
|
|
@@ -18,12 +22,19 @@ export * from './getMarksBetween'
|
|
|
18
22
|
export * from './getMarkType'
|
|
19
23
|
export * from './getNodeAttributes'
|
|
20
24
|
export * from './getNodeType'
|
|
25
|
+
export * from './getRenderedAttributes'
|
|
21
26
|
export * from './getSchema'
|
|
27
|
+
export * from './getSchemaByResolvedExtensions'
|
|
28
|
+
export * from './getSchemaTypeByName'
|
|
29
|
+
export * from './getSchemaTypeNameByName'
|
|
30
|
+
export * from './getSplittedAttributes'
|
|
22
31
|
export * from './getText'
|
|
23
32
|
export * from './getTextBetween'
|
|
24
33
|
export * from './getTextContentFromNodes'
|
|
25
34
|
export * from './getTextSerializersFromSchema'
|
|
35
|
+
export * from './injectExtensionAttributesToParseRule'
|
|
26
36
|
export * from './isActive'
|
|
37
|
+
export * from './isExtensionRulesEnabled'
|
|
27
38
|
export * from './isList'
|
|
28
39
|
export * from './isMarkActive'
|
|
29
40
|
export * from './isNodeActive'
|
|
@@ -31,3 +42,6 @@ export * from './isNodeEmpty'
|
|
|
31
42
|
export * from './isNodeSelection'
|
|
32
43
|
export * from './isTextSelection'
|
|
33
44
|
export * from './posToDOMRect'
|
|
45
|
+
export * from './resolveFocusPosition'
|
|
46
|
+
export * from './selectionToInsertionEnd'
|
|
47
|
+
export * from './splitExtensions'
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Node as ProseMirrorNode, NodeType } from '@tiptap/pm/model'
|
|
2
2
|
import { canJoin, findWrapping } from '@tiptap/pm/transform'
|
|
3
3
|
|
|
4
|
+
import { Editor } from '../Editor'
|
|
4
5
|
import { InputRule, InputRuleFinder } from '../InputRule'
|
|
5
6
|
import { ExtendedRegExpMatchArray } from '../types'
|
|
6
7
|
import { callOrReturn } from '../utilities/callOrReturn'
|
|
@@ -20,18 +21,24 @@ import { callOrReturn } from '../utilities/callOrReturn'
|
|
|
20
21
|
* return a boolean to indicate whether a join should happen.
|
|
21
22
|
*/
|
|
22
23
|
export function wrappingInputRule(config: {
|
|
23
|
-
find: InputRuleFinder
|
|
24
|
-
type: NodeType
|
|
24
|
+
find: InputRuleFinder,
|
|
25
|
+
type: NodeType,
|
|
26
|
+
keepMarks?: boolean,
|
|
27
|
+
keepAttributes?: boolean,
|
|
28
|
+
editor?: Editor
|
|
25
29
|
getAttributes?:
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
| Record<string, any>
|
|
31
|
+
| ((match: ExtendedRegExpMatchArray) => Record<string, any>)
|
|
32
|
+
| false
|
|
33
|
+
| null
|
|
34
|
+
,
|
|
35
|
+
joinPredicate?: (match: ExtendedRegExpMatchArray, node: ProseMirrorNode) => boolean,
|
|
31
36
|
}) {
|
|
32
37
|
return new InputRule({
|
|
33
38
|
find: config.find,
|
|
34
|
-
handler: ({
|
|
39
|
+
handler: ({
|
|
40
|
+
state, range, match, chain,
|
|
41
|
+
}) => {
|
|
35
42
|
const attributes = callOrReturn(config.getAttributes, undefined, match) || {}
|
|
36
43
|
const tr = state.tr.delete(range.from, range.to)
|
|
37
44
|
const $start = tr.doc.resolve(range.from)
|
|
@@ -44,6 +51,24 @@ export function wrappingInputRule(config: {
|
|
|
44
51
|
|
|
45
52
|
tr.wrap(blockRange, wrapping)
|
|
46
53
|
|
|
54
|
+
if (config.keepMarks && config.editor) {
|
|
55
|
+
const { selection, storedMarks } = state
|
|
56
|
+
const { splittableMarks } = config.editor.extensionManager
|
|
57
|
+
const marks = storedMarks || (selection.$to.parentOffset && selection.$from.marks())
|
|
58
|
+
|
|
59
|
+
if (marks) {
|
|
60
|
+
const filteredMarks = marks.filter(mark => splittableMarks.includes(mark.type.name))
|
|
61
|
+
|
|
62
|
+
tr.ensureMarks(filteredMarks)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (config.keepAttributes) {
|
|
66
|
+
/** If the nodeType is `bulletList` or `orderedList` set the `nodeType` as `listItem` */
|
|
67
|
+
const nodeType = config.type.name === 'bulletList' || config.type.name === 'orderedList' ? 'listItem' : 'taskList'
|
|
68
|
+
|
|
69
|
+
chain().updateAttributes(nodeType, attributes).run()
|
|
70
|
+
}
|
|
71
|
+
|
|
47
72
|
const before = tr.doc.resolve(range.from - 1).nodeBefore
|
|
48
73
|
|
|
49
74
|
if (
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NodeType } from '@tiptap/pm/model'
|
|
2
2
|
|
|
3
|
-
import { PasteRule } from '../PasteRule'
|
|
3
|
+
import { PasteRule, PasteRuleFinder } from '../PasteRule'
|
|
4
4
|
import { ExtendedRegExpMatchArray } from '../types'
|
|
5
5
|
import { callOrReturn } from '../utilities'
|
|
6
6
|
|
|
@@ -9,7 +9,7 @@ import { callOrReturn } from '../utilities'
|
|
|
9
9
|
* matched text is pasted into it.
|
|
10
10
|
*/
|
|
11
11
|
export function nodePasteRule(config: {
|
|
12
|
-
find:
|
|
12
|
+
find: PasteRuleFinder
|
|
13
13
|
type: NodeType
|
|
14
14
|
getAttributes?:
|
|
15
15
|
| Record<string, any>
|
package/src/types.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Mark as ProseMirrorMark, Node as ProseMirrorNode, NodeType, ParseOptions,
|
|
3
|
+
} from '@tiptap/pm/model'
|
|
2
4
|
import { EditorState, Transaction } from '@tiptap/pm/state'
|
|
3
5
|
import {
|
|
4
6
|
Decoration, EditorProps, EditorView, NodeView,
|
|
@@ -148,10 +150,14 @@ export type ValuesOf<T> = T[keyof T]
|
|
|
148
150
|
|
|
149
151
|
export type KeysWithTypeOf<T, Type> = { [P in keyof T]: T[P] extends Type ? P : never }[keyof T]
|
|
150
152
|
|
|
153
|
+
export type DecorationWithType = Decoration & {
|
|
154
|
+
type: NodeType
|
|
155
|
+
}
|
|
156
|
+
|
|
151
157
|
export type NodeViewProps = {
|
|
152
158
|
editor: Editor
|
|
153
159
|
node: ProseMirrorNode
|
|
154
|
-
decorations:
|
|
160
|
+
decorations: DecorationWithType[]
|
|
155
161
|
selected: boolean
|
|
156
162
|
extension: Node
|
|
157
163
|
getPos: () => number
|