@portabletext/editor 2.21.2 → 3.0.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/lib/_chunks-dts/index.d.ts +50 -210
- package/lib/_chunks-es/selector.is-at-the-start-of-block.js +103 -20
- package/lib/_chunks-es/selector.is-at-the-start-of-block.js.map +1 -1
- package/lib/_chunks-es/{util.get-text-block-text.js → util.slice-blocks.js} +29 -5
- package/lib/_chunks-es/util.slice-blocks.js.map +1 -0
- package/lib/_chunks-es/util.slice-text-block.js +13 -2
- package/lib/_chunks-es/util.slice-text-block.js.map +1 -1
- package/lib/behaviors/index.d.ts +1 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.js +323 -320
- package/lib/index.js.map +1 -1
- package/lib/plugins/index.d.ts +2 -133
- package/lib/plugins/index.js +2 -796
- package/lib/plugins/index.js.map +1 -1
- package/lib/selectors/index.d.ts +2 -24
- package/lib/selectors/index.js +28 -130
- package/lib/selectors/index.js.map +1 -1
- package/lib/utils/index.d.ts +3 -3
- package/lib/utils/index.js +97 -9
- package/lib/utils/index.js.map +1 -1
- package/package.json +7 -9
- package/src/behaviors/behavior.perform-event.ts +7 -7
- package/src/editor/PortableTextEditor.tsx +0 -19
- package/src/editor/create-editor.ts +0 -3
- package/src/editor/editor-machine.ts +0 -10
- package/src/editor/event-to-change.tsx +5 -1
- package/src/editor/plugins/create-with-event-listeners.ts +0 -4
- package/src/editor/plugins/createWithObjectKeys.ts +2 -1
- package/src/editor/plugins/createWithPatches.ts +3 -3
- package/src/editor/plugins/createWithPlaceholderBlock.ts +2 -1
- package/src/editor/plugins/createWithPortableTextMarkModel.ts +2 -1
- package/src/editor/plugins/with-plugins.ts +10 -14
- package/src/editor/relay-machine.ts +0 -4
- package/src/editor/sync-machine.ts +2 -2
- package/src/editor.ts +0 -4
- package/src/history/behavior.operation.history.redo.ts +67 -0
- package/src/history/behavior.operation.history.undo.ts +71 -0
- package/src/history/event.history.undo.test.tsx +672 -0
- package/src/history/history.preserving-keys.test.tsx +112 -0
- package/src/history/remote-patches.ts +20 -0
- package/src/history/slate-plugin.history.ts +146 -0
- package/src/history/slate-plugin.redoing.ts +21 -0
- package/src/history/slate-plugin.undoing.ts +21 -0
- package/src/history/slate-plugin.without-history.ts +23 -0
- package/src/history/transform-operation.ts +245 -0
- package/src/history/undo-redo-collaboration.test.tsx +541 -0
- package/src/history/undo-redo.feature +125 -0
- package/src/history/undo-redo.test.tsx +195 -0
- package/src/history/undo-step.ts +148 -0
- package/src/index.ts +0 -1
- package/src/internal-utils/applyPatch.ts +46 -1
- package/src/operations/behavior.operations.ts +2 -4
- package/src/plugins/index.ts +0 -3
- package/src/selectors/index.ts +0 -3
- package/src/test/vitest/step-definitions.tsx +88 -8
- package/src/test/vitest/test-editor.tsx +1 -1
- package/lib/_chunks-es/selector.get-selection-text.js +0 -92
- package/lib/_chunks-es/selector.get-selection-text.js.map +0 -1
- package/lib/_chunks-es/selector.get-text-before.js +0 -36
- package/lib/_chunks-es/selector.get-text-before.js.map +0 -1
- package/lib/_chunks-es/util.get-text-block-text.js.map +0 -1
- package/lib/_chunks-es/util.is-empty-text-block.js +0 -40
- package/lib/_chunks-es/util.is-empty-text-block.js.map +0 -1
- package/lib/_chunks-es/util.merge-text-blocks.js +0 -101
- package/lib/_chunks-es/util.merge-text-blocks.js.map +0 -1
- package/src/editor/plugins/createWithMaxBlocks.ts +0 -53
- package/src/editor/plugins/createWithUndoRedo.ts +0 -628
- package/src/editor/with-undo-step.ts +0 -37
- package/src/editor/withUndoRedo.ts +0 -34
- package/src/editor-event-listener.tsx +0 -28
- package/src/plugins/plugin.decorator-shortcut.ts +0 -238
- package/src/plugins/plugin.markdown.test.tsx +0 -42
- package/src/plugins/plugin.markdown.tsx +0 -131
- package/src/plugins/plugin.one-line.tsx +0 -123
- package/src/selectors/selector.get-list-state.test.ts +0 -189
- package/src/selectors/selector.get-list-state.ts +0 -96
- package/src/selectors/selector.get-selected-slice.ts +0 -13
- package/src/selectors/selector.get-trimmed-selection.test.ts +0 -657
- package/src/selectors/selector.get-trimmed-selection.ts +0 -189
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import {useEffect} from 'react'
|
|
2
|
-
import type {EditorEmittedEvent} from './editor/relay-machine'
|
|
3
|
-
import {useEditor} from './editor/use-editor'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @public
|
|
7
|
-
* @deprecated
|
|
8
|
-
* This component has been renamed. Use `EventListenerPlugin` instead.
|
|
9
|
-
*
|
|
10
|
-
* ```
|
|
11
|
-
* import {EventListenerPlugin} from '@portabletext/editor/plugins'
|
|
12
|
-
* ```
|
|
13
|
-
*/
|
|
14
|
-
export function EditorEventListener(props: {
|
|
15
|
-
on: (event: EditorEmittedEvent) => void
|
|
16
|
-
}) {
|
|
17
|
-
const editor = useEditor()
|
|
18
|
-
|
|
19
|
-
useEffect(() => {
|
|
20
|
-
const subscription = editor.on('*', props.on)
|
|
21
|
-
|
|
22
|
-
return () => {
|
|
23
|
-
subscription.unsubscribe()
|
|
24
|
-
}
|
|
25
|
-
}, [editor, props.on])
|
|
26
|
-
|
|
27
|
-
return null
|
|
28
|
-
}
|
|
@@ -1,238 +0,0 @@
|
|
|
1
|
-
import {useActorRef} from '@xstate/react'
|
|
2
|
-
import {isEqual} from 'lodash'
|
|
3
|
-
import {
|
|
4
|
-
assign,
|
|
5
|
-
fromCallback,
|
|
6
|
-
setup,
|
|
7
|
-
type AnyEventObject,
|
|
8
|
-
type CallbackLogicFunction,
|
|
9
|
-
} from 'xstate'
|
|
10
|
-
import {createDecoratorPairBehavior} from '../behaviors/behavior.decorator-pair'
|
|
11
|
-
import {effect, execute, forward} from '../behaviors/behavior.types.action'
|
|
12
|
-
import {defineBehavior} from '../behaviors/behavior.types.behavior'
|
|
13
|
-
import type {Editor} from '../editor'
|
|
14
|
-
import type {EditorSchema} from '../editor/editor-schema'
|
|
15
|
-
import {useEditor} from '../editor/use-editor'
|
|
16
|
-
import type {BlockOffset} from '../types/block-offset'
|
|
17
|
-
import {spanSelectionPointToBlockOffset} from '../utils/util.block-offset'
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* @beta
|
|
21
|
-
* @deprecated Install the plugin from `@portabletext/plugin-character-pair-decorator`
|
|
22
|
-
*/
|
|
23
|
-
export function DecoratorShortcutPlugin(config: {
|
|
24
|
-
decorator: ({schema}: {schema: EditorSchema}) => string | undefined
|
|
25
|
-
pair: {char: string; amount: number}
|
|
26
|
-
}) {
|
|
27
|
-
const editor = useEditor()
|
|
28
|
-
|
|
29
|
-
useActorRef(decoratorPairMachine, {
|
|
30
|
-
input: {
|
|
31
|
-
editor,
|
|
32
|
-
decorator: config.decorator,
|
|
33
|
-
pair: config.pair,
|
|
34
|
-
},
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
return null
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
type MarkdownEmphasisEvent =
|
|
41
|
-
| {
|
|
42
|
-
type: 'emphasis.add'
|
|
43
|
-
blockOffset: BlockOffset
|
|
44
|
-
}
|
|
45
|
-
| {
|
|
46
|
-
type: 'selection'
|
|
47
|
-
blockOffsets?: {
|
|
48
|
-
anchor: BlockOffset
|
|
49
|
-
focus: BlockOffset
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
| {
|
|
53
|
-
type: 'delete.backward'
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const emphasisListener: CallbackLogicFunction<
|
|
57
|
-
AnyEventObject,
|
|
58
|
-
MarkdownEmphasisEvent,
|
|
59
|
-
{
|
|
60
|
-
decorator: ({schema}: {schema: EditorSchema}) => string | undefined
|
|
61
|
-
editor: Editor
|
|
62
|
-
pair: {char: string; amount: number}
|
|
63
|
-
}
|
|
64
|
-
> = ({sendBack, input}) => {
|
|
65
|
-
const unregister = input.editor.registerBehavior({
|
|
66
|
-
behavior: createDecoratorPairBehavior({
|
|
67
|
-
decorator: input.decorator,
|
|
68
|
-
pair: input.pair,
|
|
69
|
-
onDecorate: (offset) => {
|
|
70
|
-
sendBack({type: 'emphasis.add', blockOffset: offset})
|
|
71
|
-
},
|
|
72
|
-
}),
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
return unregister
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const selectionListenerCallback: CallbackLogicFunction<
|
|
79
|
-
AnyEventObject,
|
|
80
|
-
MarkdownEmphasisEvent,
|
|
81
|
-
{editor: Editor}
|
|
82
|
-
> = ({sendBack, input}) => {
|
|
83
|
-
const unregister = input.editor.registerBehavior({
|
|
84
|
-
behavior: defineBehavior({
|
|
85
|
-
on: 'select',
|
|
86
|
-
guard: ({snapshot, event}) => {
|
|
87
|
-
if (!event.at) {
|
|
88
|
-
return {blockOffsets: undefined}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const anchor = spanSelectionPointToBlockOffset({
|
|
92
|
-
context: snapshot.context,
|
|
93
|
-
selectionPoint: event.at.anchor,
|
|
94
|
-
})
|
|
95
|
-
const focus = spanSelectionPointToBlockOffset({
|
|
96
|
-
context: snapshot.context,
|
|
97
|
-
selectionPoint: event.at.focus,
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
if (!anchor || !focus) {
|
|
101
|
-
return {blockOffsets: undefined}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
return {
|
|
105
|
-
blockOffsets: {
|
|
106
|
-
anchor,
|
|
107
|
-
focus,
|
|
108
|
-
},
|
|
109
|
-
}
|
|
110
|
-
},
|
|
111
|
-
actions: [
|
|
112
|
-
({event}, {blockOffsets}) => [
|
|
113
|
-
{
|
|
114
|
-
type: 'effect',
|
|
115
|
-
effect: () => {
|
|
116
|
-
sendBack({type: 'selection', blockOffsets})
|
|
117
|
-
},
|
|
118
|
-
},
|
|
119
|
-
forward(event),
|
|
120
|
-
],
|
|
121
|
-
],
|
|
122
|
-
}),
|
|
123
|
-
})
|
|
124
|
-
|
|
125
|
-
return unregister
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const deleteBackwardListenerCallback: CallbackLogicFunction<
|
|
129
|
-
AnyEventObject,
|
|
130
|
-
MarkdownEmphasisEvent,
|
|
131
|
-
{editor: Editor}
|
|
132
|
-
> = ({sendBack, input}) => {
|
|
133
|
-
const unregister = input.editor.registerBehavior({
|
|
134
|
-
behavior: defineBehavior({
|
|
135
|
-
on: 'delete.backward',
|
|
136
|
-
actions: [
|
|
137
|
-
() => [
|
|
138
|
-
execute({
|
|
139
|
-
type: 'history.undo',
|
|
140
|
-
}),
|
|
141
|
-
effect(() => {
|
|
142
|
-
sendBack({type: 'delete.backward'})
|
|
143
|
-
}),
|
|
144
|
-
],
|
|
145
|
-
],
|
|
146
|
-
}),
|
|
147
|
-
})
|
|
148
|
-
|
|
149
|
-
return unregister
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
const decoratorPairMachine = setup({
|
|
153
|
-
types: {
|
|
154
|
-
context: {} as {
|
|
155
|
-
decorator: ({schema}: {schema: EditorSchema}) => string | undefined
|
|
156
|
-
editor: Editor
|
|
157
|
-
offsetAfterEmphasis?: BlockOffset
|
|
158
|
-
pair: {char: string; amount: number}
|
|
159
|
-
},
|
|
160
|
-
input: {} as {
|
|
161
|
-
decorator: ({schema}: {schema: EditorSchema}) => string | undefined
|
|
162
|
-
editor: Editor
|
|
163
|
-
pair: {char: string; amount: number}
|
|
164
|
-
},
|
|
165
|
-
events: {} as MarkdownEmphasisEvent,
|
|
166
|
-
},
|
|
167
|
-
actors: {
|
|
168
|
-
'emphasis listener': fromCallback(emphasisListener),
|
|
169
|
-
'delete.backward listener': fromCallback(deleteBackwardListenerCallback),
|
|
170
|
-
'selection listener': fromCallback(selectionListenerCallback),
|
|
171
|
-
},
|
|
172
|
-
}).createMachine({
|
|
173
|
-
id: 'decorator pair',
|
|
174
|
-
context: ({input}) => ({
|
|
175
|
-
decorator: input.decorator,
|
|
176
|
-
editor: input.editor,
|
|
177
|
-
pair: input.pair,
|
|
178
|
-
}),
|
|
179
|
-
initial: 'idle',
|
|
180
|
-
states: {
|
|
181
|
-
'idle': {
|
|
182
|
-
invoke: [
|
|
183
|
-
{
|
|
184
|
-
src: 'emphasis listener',
|
|
185
|
-
input: ({context}) => ({
|
|
186
|
-
decorator: context.decorator,
|
|
187
|
-
editor: context.editor,
|
|
188
|
-
pair: context.pair,
|
|
189
|
-
}),
|
|
190
|
-
},
|
|
191
|
-
],
|
|
192
|
-
on: {
|
|
193
|
-
'emphasis.add': {
|
|
194
|
-
target: 'emphasis added',
|
|
195
|
-
actions: assign({
|
|
196
|
-
offsetAfterEmphasis: ({event}) => event.blockOffset,
|
|
197
|
-
}),
|
|
198
|
-
},
|
|
199
|
-
},
|
|
200
|
-
},
|
|
201
|
-
'emphasis added': {
|
|
202
|
-
exit: [
|
|
203
|
-
assign({
|
|
204
|
-
offsetAfterEmphasis: undefined,
|
|
205
|
-
}),
|
|
206
|
-
],
|
|
207
|
-
invoke: [
|
|
208
|
-
{
|
|
209
|
-
src: 'selection listener',
|
|
210
|
-
input: ({context}) => ({editor: context.editor}),
|
|
211
|
-
},
|
|
212
|
-
{
|
|
213
|
-
src: 'delete.backward listener',
|
|
214
|
-
input: ({context}) => ({editor: context.editor}),
|
|
215
|
-
},
|
|
216
|
-
],
|
|
217
|
-
on: {
|
|
218
|
-
'selection': {
|
|
219
|
-
target: 'idle',
|
|
220
|
-
guard: ({context, event}) => {
|
|
221
|
-
const selectionChanged = !isEqual(
|
|
222
|
-
{
|
|
223
|
-
anchor: context.offsetAfterEmphasis,
|
|
224
|
-
focus: context.offsetAfterEmphasis,
|
|
225
|
-
},
|
|
226
|
-
event.blockOffsets,
|
|
227
|
-
)
|
|
228
|
-
|
|
229
|
-
return selectionChanged
|
|
230
|
-
},
|
|
231
|
-
},
|
|
232
|
-
'delete.backward': {
|
|
233
|
-
target: 'idle',
|
|
234
|
-
},
|
|
235
|
-
},
|
|
236
|
-
},
|
|
237
|
-
},
|
|
238
|
-
})
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import {defineSchema} from '@portabletext/schema'
|
|
2
|
-
import {getTersePt} from '@portabletext/test'
|
|
3
|
-
import {describe, expect, test, vi} from 'vitest'
|
|
4
|
-
import {userEvent} from 'vitest/browser'
|
|
5
|
-
import {getTextMarks} from '../internal-utils/text-marks'
|
|
6
|
-
import {createTestEditor} from '../test/vitest'
|
|
7
|
-
import {MarkdownPlugin} from './plugin.markdown'
|
|
8
|
-
|
|
9
|
-
describe(MarkdownPlugin.name, () => {
|
|
10
|
-
test('Scenario: Undoing bold shortcut', async () => {
|
|
11
|
-
const {editor, locator} = await createTestEditor({
|
|
12
|
-
children: (
|
|
13
|
-
<MarkdownPlugin
|
|
14
|
-
config={{
|
|
15
|
-
boldDecorator: () => 'strong',
|
|
16
|
-
}}
|
|
17
|
-
/>
|
|
18
|
-
),
|
|
19
|
-
schemaDefinition: defineSchema({decorators: [{name: 'strong'}]}),
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
await userEvent.type(locator, '**Hello world!**')
|
|
23
|
-
|
|
24
|
-
await vi.waitFor(() => {
|
|
25
|
-
expect(getTersePt(editor.getSnapshot().context)).toEqual(['Hello world!'])
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
await vi.waitFor(() => {
|
|
29
|
-
expect(
|
|
30
|
-
getTextMarks(editor.getSnapshot().context, 'Hello world!'),
|
|
31
|
-
).toEqual(['strong'])
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
editor.send({type: 'history.undo'})
|
|
35
|
-
|
|
36
|
-
await vi.waitFor(() => {
|
|
37
|
-
expect(getTersePt(editor.getSnapshot().context)).toEqual([
|
|
38
|
-
'**Hello world!**',
|
|
39
|
-
])
|
|
40
|
-
})
|
|
41
|
-
})
|
|
42
|
-
})
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import {useEffect} from 'react'
|
|
2
|
-
import {
|
|
3
|
-
createMarkdownBehaviors,
|
|
4
|
-
type MarkdownBehaviorsConfig,
|
|
5
|
-
} from '../behaviors/behavior.markdown'
|
|
6
|
-
import type {EditorSchema} from '../editor/editor-schema'
|
|
7
|
-
import {useEditor} from '../editor/use-editor'
|
|
8
|
-
import {DecoratorShortcutPlugin} from './plugin.decorator-shortcut'
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* @beta
|
|
12
|
-
*/
|
|
13
|
-
export type MarkdownPluginConfig = MarkdownBehaviorsConfig & {
|
|
14
|
-
boldDecorator?: ({schema}: {schema: EditorSchema}) => string | undefined
|
|
15
|
-
codeDecorator?: ({schema}: {schema: EditorSchema}) => string | undefined
|
|
16
|
-
italicDecorator?: ({schema}: {schema: EditorSchema}) => string | undefined
|
|
17
|
-
strikeThroughDecorator?: ({
|
|
18
|
-
schema,
|
|
19
|
-
}: {
|
|
20
|
-
schema: EditorSchema
|
|
21
|
-
}) => string | undefined
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* @beta
|
|
26
|
-
* Add markdown behaviors for common markdown actions such as converting ### to headings, --- to HRs, and more.
|
|
27
|
-
*
|
|
28
|
-
* @example
|
|
29
|
-
* Configure the bundled markdown behaviors
|
|
30
|
-
* ```ts
|
|
31
|
-
* import {EditorProvider} from '@portabletext/editor'
|
|
32
|
-
* import {MarkdownPlugin} from '@portabletext/editor/plugins'
|
|
33
|
-
*
|
|
34
|
-
* function App() {
|
|
35
|
-
* return (
|
|
36
|
-
* <EditorProvider>
|
|
37
|
-
* <MarkdownPlugin
|
|
38
|
-
* config={{
|
|
39
|
-
* boldDecorator: ({schema}) =>
|
|
40
|
-
* schema.decorators.find((decorator) => decorator.value === 'strong')?.value,
|
|
41
|
-
* codeDecorator: ({schema}) =>
|
|
42
|
-
* schema.decorators.find((decorator) => decorator.value === 'code')?.value,
|
|
43
|
-
* italicDecorator: ({schema}) =>
|
|
44
|
-
* schema.decorators.find((decorator) => decorator.value === 'em')?.value,
|
|
45
|
-
* strikeThroughDecorator: ({schema}) =>
|
|
46
|
-
* schema.decorators.find((decorator) => decorator.value === 'strike-through')?.value,
|
|
47
|
-
* horizontalRuleObject: ({schema}) => {
|
|
48
|
-
* const name = schema.blockObjects.find(
|
|
49
|
-
* (object) => object.name === 'break',
|
|
50
|
-
* )?.name
|
|
51
|
-
* return name ? {name} : undefined
|
|
52
|
-
* },
|
|
53
|
-
* defaultStyle: ({schema}) => schema.styles[0].value,
|
|
54
|
-
* headingStyle: ({schema, level}) =>
|
|
55
|
-
* schema.styles.find((style) => style.value === `h${level}`)
|
|
56
|
-
* ?.value,
|
|
57
|
-
* blockquoteStyle: ({schema}) =>
|
|
58
|
-
* schema.styles.find((style) => style.value === 'blockquote')
|
|
59
|
-
* ?.value,
|
|
60
|
-
* unorderedListStyle: ({schema}) =>
|
|
61
|
-
* schema.lists.find((list) => list.value === 'bullet')?.value,
|
|
62
|
-
* orderedListStyle: ({schema}) =>
|
|
63
|
-
* schema.lists.find((list) => list.value === 'number')?.value,
|
|
64
|
-
* }}
|
|
65
|
-
* />
|
|
66
|
-
* {...}
|
|
67
|
-
* </EditorProvider>
|
|
68
|
-
* )
|
|
69
|
-
* }
|
|
70
|
-
* ```
|
|
71
|
-
*
|
|
72
|
-
* @deprecated Install the plugin from `@portabletext/plugin-markdown-shortcuts`
|
|
73
|
-
*/
|
|
74
|
-
export function MarkdownPlugin(props: {config: MarkdownPluginConfig}) {
|
|
75
|
-
const editor = useEditor()
|
|
76
|
-
|
|
77
|
-
useEffect(() => {
|
|
78
|
-
const behaviors = createMarkdownBehaviors(props.config)
|
|
79
|
-
|
|
80
|
-
const unregisterBehaviors = behaviors.map((behavior) =>
|
|
81
|
-
editor.registerBehavior({behavior}),
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
return () => {
|
|
85
|
-
for (const unregisterBehavior of unregisterBehaviors) {
|
|
86
|
-
unregisterBehavior()
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}, [editor, props.config])
|
|
90
|
-
|
|
91
|
-
return (
|
|
92
|
-
<>
|
|
93
|
-
{props.config.boldDecorator ? (
|
|
94
|
-
<>
|
|
95
|
-
<DecoratorShortcutPlugin
|
|
96
|
-
decorator={props.config.boldDecorator}
|
|
97
|
-
pair={{char: '*', amount: 2}}
|
|
98
|
-
/>
|
|
99
|
-
<DecoratorShortcutPlugin
|
|
100
|
-
decorator={props.config.boldDecorator}
|
|
101
|
-
pair={{char: '_', amount: 2}}
|
|
102
|
-
/>
|
|
103
|
-
</>
|
|
104
|
-
) : null}
|
|
105
|
-
{props.config.codeDecorator ? (
|
|
106
|
-
<DecoratorShortcutPlugin
|
|
107
|
-
decorator={props.config.codeDecorator}
|
|
108
|
-
pair={{char: '`', amount: 1}}
|
|
109
|
-
/>
|
|
110
|
-
) : null}
|
|
111
|
-
{props.config.italicDecorator ? (
|
|
112
|
-
<>
|
|
113
|
-
<DecoratorShortcutPlugin
|
|
114
|
-
decorator={props.config.italicDecorator}
|
|
115
|
-
pair={{char: '*', amount: 1}}
|
|
116
|
-
/>
|
|
117
|
-
<DecoratorShortcutPlugin
|
|
118
|
-
decorator={props.config.italicDecorator}
|
|
119
|
-
pair={{char: '_', amount: 1}}
|
|
120
|
-
/>
|
|
121
|
-
</>
|
|
122
|
-
) : null}
|
|
123
|
-
{props.config.strikeThroughDecorator ? (
|
|
124
|
-
<DecoratorShortcutPlugin
|
|
125
|
-
decorator={props.config.strikeThroughDecorator}
|
|
126
|
-
pair={{char: '~', amount: 2}}
|
|
127
|
-
/>
|
|
128
|
-
) : null}
|
|
129
|
-
</>
|
|
130
|
-
)
|
|
131
|
-
}
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
import {isTextBlock} from '@portabletext/schema'
|
|
2
|
-
import {execute, raise} from '../behaviors/behavior.types.action'
|
|
3
|
-
import {defineBehavior} from '../behaviors/behavior.types.behavior'
|
|
4
|
-
import {getFocusTextBlock} from '../selectors/selector.get-focus-text-block'
|
|
5
|
-
import {isSelectionExpanded} from '../selectors/selector.is-selection-expanded'
|
|
6
|
-
import {mergeTextBlocks} from '../utils/util.merge-text-blocks'
|
|
7
|
-
import {BehaviorPlugin} from './plugin.behavior'
|
|
8
|
-
|
|
9
|
-
const oneLineBehaviors = [
|
|
10
|
-
/**
|
|
11
|
-
* Hitting Enter on an expanded selection should just delete that selection
|
|
12
|
-
* without causing a line break.
|
|
13
|
-
*/
|
|
14
|
-
defineBehavior({
|
|
15
|
-
on: 'insert.break',
|
|
16
|
-
guard: ({snapshot}) =>
|
|
17
|
-
snapshot.context.selection && isSelectionExpanded(snapshot)
|
|
18
|
-
? {selection: snapshot.context.selection}
|
|
19
|
-
: false,
|
|
20
|
-
actions: [(_, {selection}) => [execute({type: 'delete', at: selection})]],
|
|
21
|
-
}),
|
|
22
|
-
/**
|
|
23
|
-
* All other cases of `insert.break` should be aborted.
|
|
24
|
-
*/
|
|
25
|
-
defineBehavior({
|
|
26
|
-
on: 'insert.break',
|
|
27
|
-
actions: [],
|
|
28
|
-
}),
|
|
29
|
-
/**
|
|
30
|
-
* `insert.block` `before` or `after` is not allowed in a one-line editor.
|
|
31
|
-
*/
|
|
32
|
-
defineBehavior({
|
|
33
|
-
on: 'insert.block',
|
|
34
|
-
guard: ({event}) =>
|
|
35
|
-
event.placement === 'before' || event.placement === 'after',
|
|
36
|
-
actions: [],
|
|
37
|
-
}),
|
|
38
|
-
/**
|
|
39
|
-
* An ordinary `insert.block` is acceptable if it's a text block. In that
|
|
40
|
-
* case it will get merged into the existing text block.
|
|
41
|
-
*/
|
|
42
|
-
defineBehavior({
|
|
43
|
-
on: 'insert.block',
|
|
44
|
-
guard: ({snapshot, event}) => {
|
|
45
|
-
const focusTextBlock = getFocusTextBlock(snapshot)
|
|
46
|
-
|
|
47
|
-
if (!focusTextBlock || !isTextBlock(snapshot.context, event.block)) {
|
|
48
|
-
return false
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return true
|
|
52
|
-
},
|
|
53
|
-
actions: [
|
|
54
|
-
({event}) => [
|
|
55
|
-
execute({
|
|
56
|
-
type: 'insert.block',
|
|
57
|
-
block: event.block,
|
|
58
|
-
placement: 'auto',
|
|
59
|
-
select: 'end',
|
|
60
|
-
}),
|
|
61
|
-
],
|
|
62
|
-
],
|
|
63
|
-
}),
|
|
64
|
-
/**
|
|
65
|
-
* Fallback Behavior to avoid `insert.block` in case the Behaviors above all
|
|
66
|
-
* end up with a falsy guard.
|
|
67
|
-
*/
|
|
68
|
-
defineBehavior({
|
|
69
|
-
on: 'insert.block',
|
|
70
|
-
actions: [],
|
|
71
|
-
}),
|
|
72
|
-
/**
|
|
73
|
-
* If multiple blocks are inserted, then the non-text blocks are filtered out
|
|
74
|
-
* and the text blocks are merged into one block
|
|
75
|
-
*/
|
|
76
|
-
defineBehavior({
|
|
77
|
-
on: 'insert.blocks',
|
|
78
|
-
guard: ({snapshot, event}) => {
|
|
79
|
-
const textBlocks = event.blocks.filter((block) =>
|
|
80
|
-
isTextBlock(snapshot.context, block),
|
|
81
|
-
)
|
|
82
|
-
|
|
83
|
-
if (textBlocks.length === 0) {
|
|
84
|
-
return false
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return textBlocks.reduce((targetBlock, incomingBlock) => {
|
|
88
|
-
return mergeTextBlocks({
|
|
89
|
-
context: snapshot.context,
|
|
90
|
-
targetBlock,
|
|
91
|
-
incomingBlock,
|
|
92
|
-
})
|
|
93
|
-
})
|
|
94
|
-
},
|
|
95
|
-
actions: [
|
|
96
|
-
// `insert.block` is raised so the Behavior above can handle the
|
|
97
|
-
// insertion
|
|
98
|
-
(_, block) => [raise({type: 'insert.block', block, placement: 'auto'})],
|
|
99
|
-
],
|
|
100
|
-
}),
|
|
101
|
-
/**
|
|
102
|
-
* Fallback Behavior to avoid `insert.blocks` in case the Behavior above
|
|
103
|
-
* ends up with a falsy guard.
|
|
104
|
-
*/
|
|
105
|
-
defineBehavior({
|
|
106
|
-
on: 'insert.blocks',
|
|
107
|
-
actions: [],
|
|
108
|
-
}),
|
|
109
|
-
]
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* @beta
|
|
113
|
-
* Restrict the editor to one line. The plugin takes care of blocking
|
|
114
|
-
* `insert.break` events and smart handling of other `insert.*` events.
|
|
115
|
-
*
|
|
116
|
-
* Place it with as high priority as possible to make sure other plugins don't
|
|
117
|
-
* overwrite `insert.*` events before this plugin gets a chance to do so.
|
|
118
|
-
*
|
|
119
|
-
* @deprecated Install the plugin from `@portabletext/plugin-one-line`
|
|
120
|
-
*/
|
|
121
|
-
export function OneLinePlugin() {
|
|
122
|
-
return <BehaviorPlugin behaviors={oneLineBehaviors} />
|
|
123
|
-
}
|