@portabletext/editor 2.8.0 → 2.8.2
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/lib/_chunks-cjs/selector.is-selection-expanded.cjs +10 -4
- package/lib/_chunks-cjs/selector.is-selection-expanded.cjs.map +1 -1
- package/lib/_chunks-cjs/util.merge-text-blocks.cjs +0 -1
- package/lib/_chunks-cjs/util.merge-text-blocks.cjs.map +1 -1
- package/lib/_chunks-cjs/util.slice-blocks.cjs +3 -6
- package/lib/_chunks-cjs/util.slice-blocks.cjs.map +1 -1
- package/lib/_chunks-dts/behavior.types.action.d.cts +27 -31
- package/lib/_chunks-dts/behavior.types.action.d.ts +18 -22
- package/lib/_chunks-es/selector.is-selection-expanded.js +10 -4
- package/lib/_chunks-es/selector.is-selection-expanded.js.map +1 -1
- package/lib/_chunks-es/util.merge-text-blocks.js +0 -1
- package/lib/_chunks-es/util.merge-text-blocks.js.map +1 -1
- package/lib/_chunks-es/util.slice-blocks.js +3 -6
- package/lib/_chunks-es/util.slice-blocks.js.map +1 -1
- package/lib/index.cjs +28 -51
- package/lib/index.cjs.map +1 -1
- package/lib/index.js +28 -51
- package/lib/index.js.map +1 -1
- package/lib/plugins/index.d.cts +3 -3
- package/lib/utils/index.d.ts +2 -2
- package/package.json +5 -5
- package/src/behaviors/behavior.abstract.split.ts +0 -1
- package/src/converters/converter.portable-text.ts +0 -1
- package/src/converters/converter.text-html.ts +0 -1
- package/src/converters/converter.text-plain.ts +0 -1
- package/src/editor/Editable.tsx +0 -1
- package/src/editor/PortableTextEditor.tsx +1 -1
- package/src/editor/plugins/createWithEditableAPI.ts +70 -28
- package/src/index.ts +1 -1
- package/src/internal-utils/parse-blocks.test.ts +23 -23
- package/src/internal-utils/parse-blocks.ts +11 -23
- package/src/internal-utils/test-editor.tsx +15 -21
- package/src/operations/behavior.operation.annotation.add.ts +2 -47
- package/src/operations/behavior.operation.block.set.ts +1 -1
- package/src/operations/behavior.operation.block.unset.ts +2 -2
- package/src/operations/behavior.operation.insert.block.ts +1 -1
- package/src/operations/behavior.operations.ts +1 -2
- package/src/plugins/plugin.internal.auto-close-brackets.test.tsx +25 -71
- package/src/plugins/plugin.markdown.test.tsx +12 -30
- package/src/selectors/selector.get-selected-value.test.ts +748 -0
- package/src/selectors/selector.get-selected-value.ts +28 -7
- package/src/selectors/selector.get-trimmed-selection.test.ts +0 -1
- package/src/types/editor.ts +19 -3
- package/src/utils/util.merge-text-blocks.ts +1 -1
- package/src/utils/util.slice-blocks.ts +3 -3
- package/src/utils/util.slice-blocks.test.ts +0 -499
|
@@ -1,29 +1,9 @@
|
|
|
1
|
-
import type {Path} from '@sanity/types'
|
|
2
1
|
import {Editor, Node, Range, Text, Transforms} from 'slate'
|
|
3
2
|
import {parseAnnotation} from '../internal-utils/parse-blocks'
|
|
4
3
|
import type {BehaviorOperationImplementation} from './behavior.operations'
|
|
5
4
|
|
|
6
|
-
/**
|
|
7
|
-
* @public
|
|
8
|
-
*/
|
|
9
|
-
export type AddedAnnotationPaths = {
|
|
10
|
-
/**
|
|
11
|
-
* @deprecated An annotation may be applied to multiple blocks, resulting
|
|
12
|
-
* in multiple `markDef`'s being created. Use `markDefPaths` instead.
|
|
13
|
-
*/
|
|
14
|
-
markDefPath: Path
|
|
15
|
-
markDefPaths: Array<Path>
|
|
16
|
-
/**
|
|
17
|
-
* @deprecated Does not return anything meaningful since an annotation
|
|
18
|
-
* can span multiple blocks and spans. If references the span closest
|
|
19
|
-
* to the focus point of the selection.
|
|
20
|
-
*/
|
|
21
|
-
spanPath: Path
|
|
22
|
-
}
|
|
23
|
-
|
|
24
5
|
export const addAnnotationOperationImplementation: BehaviorOperationImplementation<
|
|
25
|
-
'annotation.add'
|
|
26
|
-
AddedAnnotationPaths | undefined
|
|
6
|
+
'annotation.add'
|
|
27
7
|
> = ({context, operation}) => {
|
|
28
8
|
const parsedAnnotation = parseAnnotation({
|
|
29
9
|
annotation: {
|
|
@@ -31,7 +11,7 @@ export const addAnnotationOperationImplementation: BehaviorOperationImplementati
|
|
|
31
11
|
...operation.annotation.value,
|
|
32
12
|
},
|
|
33
13
|
context,
|
|
34
|
-
options: {
|
|
14
|
+
options: {validateFields: true},
|
|
35
15
|
})
|
|
36
16
|
|
|
37
17
|
if (!parsedAnnotation) {
|
|
@@ -46,11 +26,6 @@ export const addAnnotationOperationImplementation: BehaviorOperationImplementati
|
|
|
46
26
|
return
|
|
47
27
|
}
|
|
48
28
|
|
|
49
|
-
let paths: AddedAnnotationPaths | undefined
|
|
50
|
-
let spanPath: Path | undefined
|
|
51
|
-
let markDefPath: Path | undefined
|
|
52
|
-
const markDefPaths: Path[] = []
|
|
53
|
-
|
|
54
29
|
const selectedBlocks = Editor.nodes(editor, {
|
|
55
30
|
at: editor.selection,
|
|
56
31
|
match: (node) => editor.isTextBlock(node),
|
|
@@ -92,14 +67,6 @@ export const addAnnotationOperationImplementation: BehaviorOperationImplementati
|
|
|
92
67
|
},
|
|
93
68
|
{at: blockPath},
|
|
94
69
|
)
|
|
95
|
-
|
|
96
|
-
markDefPath = [{_key: block._key}, 'markDefs', {_key: annotationKey}]
|
|
97
|
-
|
|
98
|
-
if (Range.isBackward(editor.selection)) {
|
|
99
|
-
markDefPaths.unshift(markDefPath)
|
|
100
|
-
} else {
|
|
101
|
-
markDefPaths.push(markDefPath)
|
|
102
|
-
}
|
|
103
70
|
}
|
|
104
71
|
|
|
105
72
|
Transforms.setNodes(editor, {}, {match: Text.isText, split: true})
|
|
@@ -124,20 +91,8 @@ export const addAnnotationOperationImplementation: BehaviorOperationImplementati
|
|
|
124
91
|
},
|
|
125
92
|
{at: path},
|
|
126
93
|
)
|
|
127
|
-
|
|
128
|
-
spanPath = [{_key: block._key}, 'children', {_key: span._key}]
|
|
129
94
|
}
|
|
130
95
|
|
|
131
96
|
blockIndex++
|
|
132
97
|
}
|
|
133
|
-
|
|
134
|
-
if (markDefPath && spanPath) {
|
|
135
|
-
paths = {
|
|
136
|
-
markDefPath,
|
|
137
|
-
markDefPaths,
|
|
138
|
-
spanPath,
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
return paths
|
|
143
98
|
}
|
|
@@ -51,7 +51,7 @@ export const blockUnsetOperationImplementation: BehaviorOperationImplementation<
|
|
|
51
51
|
const updatedTextBlock = parseBlock({
|
|
52
52
|
context,
|
|
53
53
|
block: omit(parsedBlock, propsToRemove),
|
|
54
|
-
options: {
|
|
54
|
+
options: {validateFields: true},
|
|
55
55
|
})
|
|
56
56
|
|
|
57
57
|
if (!updatedTextBlock) {
|
|
@@ -81,7 +81,7 @@ export const blockUnsetOperationImplementation: BehaviorOperationImplementation<
|
|
|
81
81
|
parsedBlock,
|
|
82
82
|
operation.props.filter((prop) => prop !== '_type'),
|
|
83
83
|
),
|
|
84
|
-
options: {
|
|
84
|
+
options: {validateFields: true},
|
|
85
85
|
})
|
|
86
86
|
|
|
87
87
|
if (!updatedBlockObject) {
|
|
@@ -24,7 +24,7 @@ export const insertBlockOperationImplementation: BehaviorOperationImplementation
|
|
|
24
24
|
const parsedBlock = parseBlock({
|
|
25
25
|
block: operation.block,
|
|
26
26
|
context,
|
|
27
|
-
options: {
|
|
27
|
+
options: {validateFields: true},
|
|
28
28
|
})
|
|
29
29
|
|
|
30
30
|
if (!parsedBlock) {
|
|
@@ -32,14 +32,13 @@ export type BehaviorOperationImplementationContext = Pick<
|
|
|
32
32
|
|
|
33
33
|
export type BehaviorOperationImplementation<
|
|
34
34
|
TBehaviorOperationType extends BehaviorOperation['type'],
|
|
35
|
-
TReturnType = void,
|
|
36
35
|
> = ({
|
|
37
36
|
context,
|
|
38
37
|
operation,
|
|
39
38
|
}: {
|
|
40
39
|
context: BehaviorOperationImplementationContext
|
|
41
40
|
operation: PickFromUnion<BehaviorOperation, 'type', TBehaviorOperationType>
|
|
42
|
-
}) =>
|
|
41
|
+
}) => void
|
|
43
42
|
|
|
44
43
|
type BehaviorOperation = OmitFromUnion<
|
|
45
44
|
SyntheticBehaviorEvent,
|
|
@@ -1,117 +1,71 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {page, userEvent} from '@vitest/browser/context'
|
|
4
|
-
import React from 'react'
|
|
1
|
+
import {getTersePt} from '@portabletext/test'
|
|
2
|
+
import {userEvent} from '@vitest/browser/context'
|
|
5
3
|
import {describe, expect, test, vi} from 'vitest'
|
|
6
|
-
import {
|
|
7
|
-
import {EditorProvider, PortableTextEditable, type Editor} from '..'
|
|
8
|
-
import {EditorRefPlugin} from './plugin.editor-ref'
|
|
4
|
+
import {createTestEditor} from '../internal-utils/test-editor'
|
|
9
5
|
import {AutoCloseBracketsPlugin} from './plugin.internal.auto-close-brackets'
|
|
10
6
|
|
|
11
7
|
describe(AutoCloseBracketsPlugin.name, () => {
|
|
12
8
|
test('One-character text insertion', async () => {
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
initialConfig={{
|
|
18
|
-
keyGenerator: createTestKeyGenerator(),
|
|
19
|
-
schemaDefinition: defineSchema({}),
|
|
20
|
-
}}
|
|
21
|
-
>
|
|
22
|
-
<EditorRefPlugin ref={editorRef} />
|
|
23
|
-
<PortableTextEditable />
|
|
24
|
-
<AutoCloseBracketsPlugin />
|
|
25
|
-
</EditorProvider>,
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
const locator = page.getByRole('textbox')
|
|
29
|
-
await vi.waitFor(() => expect.element(locator).toBeInTheDocument())
|
|
9
|
+
const {editor, locator} = await createTestEditor({
|
|
10
|
+
children: <AutoCloseBracketsPlugin />,
|
|
11
|
+
})
|
|
12
|
+
|
|
30
13
|
await userEvent.click(locator)
|
|
31
14
|
|
|
32
|
-
|
|
15
|
+
editor.send({type: 'insert.text', text: '('})
|
|
33
16
|
|
|
34
17
|
await vi.waitFor(() => {
|
|
35
|
-
expect(getTersePt(
|
|
36
|
-
'()',
|
|
37
|
-
])
|
|
18
|
+
expect(getTersePt(editor.getSnapshot().context)).toEqual(['()'])
|
|
38
19
|
})
|
|
39
20
|
|
|
40
21
|
await userEvent.type(locator, 'foo')
|
|
41
22
|
|
|
42
23
|
await vi.waitFor(() => {
|
|
43
|
-
expect(getTersePt(
|
|
44
|
-
'(foo)',
|
|
45
|
-
])
|
|
24
|
+
expect(getTersePt(editor.getSnapshot().context)).toEqual(['(foo)'])
|
|
46
25
|
})
|
|
47
26
|
|
|
48
|
-
|
|
27
|
+
editor.send({type: 'history.undo'})
|
|
49
28
|
|
|
50
29
|
await vi.waitFor(() => {
|
|
51
|
-
expect(getTersePt(
|
|
52
|
-
'()',
|
|
53
|
-
])
|
|
30
|
+
expect(getTersePt(editor.getSnapshot().context)).toEqual(['()'])
|
|
54
31
|
})
|
|
55
32
|
|
|
56
|
-
|
|
33
|
+
editor.send({type: 'history.undo'})
|
|
57
34
|
|
|
58
35
|
await vi.waitFor(() => {
|
|
59
|
-
expect(getTersePt(
|
|
60
|
-
'(',
|
|
61
|
-
])
|
|
36
|
+
expect(getTersePt(editor.getSnapshot().context)).toEqual(['('])
|
|
62
37
|
})
|
|
63
38
|
})
|
|
64
39
|
|
|
65
40
|
test('Two-character text insertion', async () => {
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
initialConfig={{
|
|
71
|
-
keyGenerator: createTestKeyGenerator(),
|
|
72
|
-
schemaDefinition: defineSchema({}),
|
|
73
|
-
}}
|
|
74
|
-
>
|
|
75
|
-
<EditorRefPlugin ref={editorRef} />
|
|
76
|
-
<PortableTextEditable />
|
|
77
|
-
<AutoCloseBracketsPlugin />
|
|
78
|
-
</EditorProvider>,
|
|
79
|
-
)
|
|
80
|
-
|
|
81
|
-
const locator = page.getByRole('textbox')
|
|
82
|
-
await vi.waitFor(() => expect.element(locator).toBeInTheDocument())
|
|
41
|
+
const {editor, locator} = await createTestEditor({
|
|
42
|
+
children: <AutoCloseBracketsPlugin />,
|
|
43
|
+
})
|
|
44
|
+
|
|
83
45
|
await userEvent.click(locator)
|
|
84
46
|
|
|
85
|
-
|
|
47
|
+
editor.send({type: 'insert.text', text: '(f'})
|
|
86
48
|
|
|
87
49
|
await vi.waitFor(() => {
|
|
88
|
-
expect(getTersePt(
|
|
89
|
-
'(f)',
|
|
90
|
-
])
|
|
50
|
+
expect(getTersePt(editor.getSnapshot().context)).toEqual(['(f)'])
|
|
91
51
|
})
|
|
92
52
|
|
|
93
53
|
await userEvent.type(locator, 'oo')
|
|
94
54
|
|
|
95
55
|
await vi.waitFor(() => {
|
|
96
|
-
expect(getTersePt(
|
|
97
|
-
'(foo)',
|
|
98
|
-
])
|
|
56
|
+
expect(getTersePt(editor.getSnapshot().context)).toEqual(['(foo)'])
|
|
99
57
|
})
|
|
100
58
|
|
|
101
|
-
|
|
59
|
+
editor.send({type: 'history.undo'})
|
|
102
60
|
|
|
103
61
|
await vi.waitFor(() => {
|
|
104
|
-
expect(getTersePt(
|
|
105
|
-
'(f)',
|
|
106
|
-
])
|
|
62
|
+
expect(getTersePt(editor.getSnapshot().context)).toEqual(['(f)'])
|
|
107
63
|
})
|
|
108
64
|
|
|
109
|
-
|
|
65
|
+
editor.send({type: 'history.undo'})
|
|
110
66
|
|
|
111
67
|
await vi.waitFor(() => {
|
|
112
|
-
expect(getTersePt(
|
|
113
|
-
'(f',
|
|
114
|
-
])
|
|
68
|
+
expect(getTersePt(editor.getSnapshot().context)).toEqual(['(f'])
|
|
115
69
|
})
|
|
116
70
|
})
|
|
117
71
|
})
|
|
@@ -1,58 +1,40 @@
|
|
|
1
1
|
import {defineSchema} from '@portabletext/schema'
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import React from 'react'
|
|
2
|
+
import {getTersePt} from '@portabletext/test'
|
|
3
|
+
import {userEvent} from '@vitest/browser/context'
|
|
5
4
|
import {describe, expect, test, vi} from 'vitest'
|
|
6
|
-
import {
|
|
7
|
-
import {PortableTextEditable, type Editor} from '..'
|
|
8
|
-
import {EditorProvider} from '../editor/editor-provider'
|
|
5
|
+
import {createTestEditor} from '../internal-utils/test-editor'
|
|
9
6
|
import {getTextMarks} from '../internal-utils/text-marks'
|
|
10
|
-
import {EditorRefPlugin} from './plugin.editor-ref'
|
|
11
7
|
import {MarkdownPlugin} from './plugin.markdown'
|
|
12
8
|
|
|
13
9
|
describe(MarkdownPlugin.name, () => {
|
|
14
10
|
test('Scenario: Undoing bold shortcut', async () => {
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
render(
|
|
18
|
-
<EditorProvider
|
|
19
|
-
initialConfig={{
|
|
20
|
-
keyGenerator: createTestKeyGenerator(),
|
|
21
|
-
schemaDefinition: defineSchema({decorators: [{name: 'strong'}]}),
|
|
22
|
-
}}
|
|
23
|
-
>
|
|
24
|
-
<EditorRefPlugin ref={editorRef} />
|
|
25
|
-
<PortableTextEditable />
|
|
11
|
+
const {editor, locator} = await createTestEditor({
|
|
12
|
+
children: (
|
|
26
13
|
<MarkdownPlugin
|
|
27
14
|
config={{
|
|
28
15
|
boldDecorator: () => 'strong',
|
|
29
16
|
}}
|
|
30
17
|
/>
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const locator = page.getByRole('textbox')
|
|
35
|
-
|
|
36
|
-
await vi.waitFor(() => expect.element(locator).toBeInTheDocument())
|
|
18
|
+
),
|
|
19
|
+
schemaDefinition: defineSchema({decorators: [{name: 'strong'}]}),
|
|
20
|
+
})
|
|
37
21
|
|
|
38
22
|
await userEvent.type(locator, '**Hello world!**')
|
|
39
23
|
|
|
40
24
|
await vi.waitFor(() => {
|
|
41
|
-
expect(getTersePt(
|
|
42
|
-
'Hello world!',
|
|
43
|
-
])
|
|
25
|
+
expect(getTersePt(editor.getSnapshot().context)).toEqual(['Hello world!'])
|
|
44
26
|
})
|
|
45
27
|
|
|
46
28
|
await vi.waitFor(() => {
|
|
47
29
|
expect(
|
|
48
|
-
getTextMarks(
|
|
30
|
+
getTextMarks(editor.getSnapshot().context, 'Hello world!'),
|
|
49
31
|
).toEqual(['strong'])
|
|
50
32
|
})
|
|
51
33
|
|
|
52
|
-
|
|
34
|
+
editor.send({type: 'history.undo'})
|
|
53
35
|
|
|
54
36
|
await vi.waitFor(() => {
|
|
55
|
-
expect(getTersePt(
|
|
37
|
+
expect(getTersePt(editor.getSnapshot().context)).toEqual([
|
|
56
38
|
'**Hello world!**',
|
|
57
39
|
])
|
|
58
40
|
})
|