@tiptap/core 3.10.8 → 3.11.0
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 +132 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +61 -4
- package/dist/index.d.ts +61 -4
- package/dist/index.js +125 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/Editor.ts +5 -0
- package/src/commands/index.ts +2 -0
- package/src/commands/setTextDirection.ts +51 -0
- package/src/commands/unsetTextDirection.ts +51 -0
- package/src/extensions/index.ts +1 -0
- package/src/extensions/textDirection.ts +86 -0
- package/src/types.ts +10 -1
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
|
+
"version": "3.11.0",
|
|
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.
|
|
55
|
+
"@tiptap/pm": "^3.11.0"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
|
-
"@tiptap/pm": "^3.
|
|
58
|
+
"@tiptap/pm": "^3.11.0"
|
|
59
59
|
},
|
|
60
60
|
"repository": {
|
|
61
61
|
"type": "git",
|
package/src/Editor.ts
CHANGED
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
Keymap,
|
|
18
18
|
Paste,
|
|
19
19
|
Tabindex,
|
|
20
|
+
TextDirection,
|
|
20
21
|
} from './extensions/index.js'
|
|
21
22
|
import { createDocument } from './helpers/createDocument.js'
|
|
22
23
|
import { getAttributes } from './helpers/getAttributes.js'
|
|
@@ -87,6 +88,7 @@ export class Editor extends EventEmitter<EditorEvents> {
|
|
|
87
88
|
extensions: [],
|
|
88
89
|
autofocus: false,
|
|
89
90
|
editable: true,
|
|
91
|
+
textDirection: undefined,
|
|
90
92
|
editorProps: {},
|
|
91
93
|
parseOptions: {},
|
|
92
94
|
coreExtensionOptions: {},
|
|
@@ -430,6 +432,9 @@ export class Editor extends EventEmitter<EditorEvents> {
|
|
|
430
432
|
Drop,
|
|
431
433
|
Paste,
|
|
432
434
|
Delete,
|
|
435
|
+
TextDirection.configure({
|
|
436
|
+
direction: this.options.textDirection,
|
|
437
|
+
}),
|
|
433
438
|
].filter(ext => {
|
|
434
439
|
if (typeof this.options.enableCoreExtensions === 'object') {
|
|
435
440
|
return (
|
package/src/commands/index.ts
CHANGED
|
@@ -39,6 +39,7 @@ export * from './setMark.js'
|
|
|
39
39
|
export * from './setMeta.js'
|
|
40
40
|
export * from './setNode.js'
|
|
41
41
|
export * from './setNodeSelection.js'
|
|
42
|
+
export * from './setTextDirection.js'
|
|
42
43
|
export * from './setTextSelection.js'
|
|
43
44
|
export * from './sinkListItem.js'
|
|
44
45
|
export * from './splitBlock.js'
|
|
@@ -50,6 +51,7 @@ export * from './toggleWrap.js'
|
|
|
50
51
|
export * from './undoInputRule.js'
|
|
51
52
|
export * from './unsetAllMarks.js'
|
|
52
53
|
export * from './unsetMark.js'
|
|
54
|
+
export * from './unsetTextDirection.js'
|
|
53
55
|
export * from './updateAttributes.js'
|
|
54
56
|
export * from './wrapIn.js'
|
|
55
57
|
export * from './wrapInList.js'
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { Range, RawCommands } from '../types.js'
|
|
2
|
+
|
|
3
|
+
declare module '@tiptap/core' {
|
|
4
|
+
interface Commands<ReturnType> {
|
|
5
|
+
setTextDirection: {
|
|
6
|
+
/**
|
|
7
|
+
* Set the text direction for nodes.
|
|
8
|
+
* If no position is provided, it will use the current selection.
|
|
9
|
+
* @param direction The text direction to set ('ltr', 'rtl', or 'auto')
|
|
10
|
+
* @param position Optional position or range to apply the direction to
|
|
11
|
+
* @example editor.commands.setTextDirection('rtl')
|
|
12
|
+
* @example editor.commands.setTextDirection('ltr', { from: 0, to: 10 })
|
|
13
|
+
*/
|
|
14
|
+
setTextDirection: (direction: 'ltr' | 'rtl' | 'auto', position?: number | Range) => ReturnType
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const setTextDirection: RawCommands['setTextDirection'] =
|
|
20
|
+
(direction, position) =>
|
|
21
|
+
({ tr, state, dispatch }) => {
|
|
22
|
+
const { selection } = state
|
|
23
|
+
let from: number
|
|
24
|
+
let to: number
|
|
25
|
+
|
|
26
|
+
if (typeof position === 'number') {
|
|
27
|
+
from = position
|
|
28
|
+
to = position
|
|
29
|
+
} else if (position && 'from' in position && 'to' in position) {
|
|
30
|
+
from = position.from
|
|
31
|
+
to = position.to
|
|
32
|
+
} else {
|
|
33
|
+
from = selection.from
|
|
34
|
+
to = selection.to
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (dispatch) {
|
|
38
|
+
tr.doc.nodesBetween(from, to, (node, pos) => {
|
|
39
|
+
if (node.isText) {
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
tr.setNodeMarkup(pos, undefined, {
|
|
44
|
+
...node.attrs,
|
|
45
|
+
dir: direction,
|
|
46
|
+
})
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return true
|
|
51
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { Range, RawCommands } from '../types.js'
|
|
2
|
+
|
|
3
|
+
declare module '@tiptap/core' {
|
|
4
|
+
interface Commands<ReturnType> {
|
|
5
|
+
unsetTextDirection: {
|
|
6
|
+
/**
|
|
7
|
+
* Remove the text direction attribute from nodes.
|
|
8
|
+
* If no position is provided, it will use the current selection.
|
|
9
|
+
* @param position Optional position or range to remove the direction from
|
|
10
|
+
* @example editor.commands.unsetTextDirection()
|
|
11
|
+
* @example editor.commands.unsetTextDirection({ from: 0, to: 10 })
|
|
12
|
+
*/
|
|
13
|
+
unsetTextDirection: (position?: number | Range) => ReturnType
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const unsetTextDirection: RawCommands['unsetTextDirection'] =
|
|
19
|
+
position =>
|
|
20
|
+
({ tr, state, dispatch }) => {
|
|
21
|
+
const { selection } = state
|
|
22
|
+
let from: number
|
|
23
|
+
let to: number
|
|
24
|
+
|
|
25
|
+
if (typeof position === 'number') {
|
|
26
|
+
from = position
|
|
27
|
+
to = position
|
|
28
|
+
} else if (position && 'from' in position && 'to' in position) {
|
|
29
|
+
from = position.from
|
|
30
|
+
to = position.to
|
|
31
|
+
} else {
|
|
32
|
+
from = selection.from
|
|
33
|
+
to = selection.to
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (dispatch) {
|
|
37
|
+
tr.doc.nodesBetween(from, to, (node, pos) => {
|
|
38
|
+
if (node.isText) {
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const newAttrs = { ...node.attrs }
|
|
43
|
+
|
|
44
|
+
delete newAttrs.dir
|
|
45
|
+
|
|
46
|
+
tr.setNodeMarkup(pos, undefined, newAttrs)
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return true
|
|
51
|
+
}
|
package/src/extensions/index.ts
CHANGED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Plugin, PluginKey } from '@tiptap/pm/state'
|
|
2
|
+
|
|
3
|
+
import { Extension } from '../Extension.js'
|
|
4
|
+
import { splitExtensions } from '../helpers/splitExtensions.js'
|
|
5
|
+
|
|
6
|
+
export interface TextDirectionOptions {
|
|
7
|
+
direction: 'ltr' | 'rtl' | 'auto' | undefined
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The TextDirection extension adds support for setting text direction (LTR/RTL/auto)
|
|
12
|
+
* on all nodes in the editor.
|
|
13
|
+
*
|
|
14
|
+
* This extension adds a global `dir` attribute to all node types, which can be used
|
|
15
|
+
* to control bidirectional text rendering. The direction can be set globally via
|
|
16
|
+
* editor options or per-node using commands.
|
|
17
|
+
*/
|
|
18
|
+
export const TextDirection = Extension.create<TextDirectionOptions>({
|
|
19
|
+
name: 'textDirection',
|
|
20
|
+
|
|
21
|
+
addOptions() {
|
|
22
|
+
return {
|
|
23
|
+
direction: undefined,
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
addGlobalAttributes() {
|
|
28
|
+
// Only add the dir attribute to nodes if text direction is configured
|
|
29
|
+
// This prevents null/undefined values from appearing in JSON exports
|
|
30
|
+
if (!this.options.direction) {
|
|
31
|
+
return []
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const { nodeExtensions } = splitExtensions(this.extensions)
|
|
35
|
+
|
|
36
|
+
return [
|
|
37
|
+
{
|
|
38
|
+
types: nodeExtensions.filter(extension => extension.name !== 'text').map(extension => extension.name),
|
|
39
|
+
attributes: {
|
|
40
|
+
dir: {
|
|
41
|
+
default: this.options.direction,
|
|
42
|
+
parseHTML: element => {
|
|
43
|
+
const dir = element.getAttribute('dir')
|
|
44
|
+
|
|
45
|
+
if (dir && (dir === 'ltr' || dir === 'rtl' || dir === 'auto')) {
|
|
46
|
+
return dir
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return this.options.direction
|
|
50
|
+
},
|
|
51
|
+
renderHTML: attributes => {
|
|
52
|
+
if (!attributes.dir) {
|
|
53
|
+
return {}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
dir: attributes.dir,
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
]
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
addProseMirrorPlugins() {
|
|
67
|
+
return [
|
|
68
|
+
new Plugin({
|
|
69
|
+
key: new PluginKey('textDirection'),
|
|
70
|
+
props: {
|
|
71
|
+
attributes: (): { [name: string]: string } => {
|
|
72
|
+
const direction = this.options.direction
|
|
73
|
+
|
|
74
|
+
if (!direction) {
|
|
75
|
+
return {}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
dir: direction,
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
}),
|
|
84
|
+
]
|
|
85
|
+
},
|
|
86
|
+
})
|
package/src/types.ts
CHANGED
|
@@ -292,6 +292,14 @@ export interface EditorOptions {
|
|
|
292
292
|
* Whether the editor is editable
|
|
293
293
|
*/
|
|
294
294
|
editable: boolean
|
|
295
|
+
/**
|
|
296
|
+
* The default text direction for all content in the editor.
|
|
297
|
+
* When set to 'ltr' or 'rtl', all nodes will have the corresponding dir attribute.
|
|
298
|
+
* When set to 'auto', the dir attribute will be set based on content detection.
|
|
299
|
+
* When undefined, no dir attribute will be added.
|
|
300
|
+
* @default undefined
|
|
301
|
+
*/
|
|
302
|
+
textDirection?: 'ltr' | 'rtl' | 'auto'
|
|
295
303
|
/**
|
|
296
304
|
* The editor's props
|
|
297
305
|
*/
|
|
@@ -357,7 +365,8 @@ export interface EditorOptions {
|
|
|
357
365
|
| 'tabindex'
|
|
358
366
|
| 'drop'
|
|
359
367
|
| 'paste'
|
|
360
|
-
| 'delete'
|
|
368
|
+
| 'delete'
|
|
369
|
+
| 'textDirection',
|
|
361
370
|
false
|
|
362
371
|
>
|
|
363
372
|
>
|