@portabletext/editor 1.47.0 → 1.47.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/behavior.core.cjs +7 -7
- package/lib/_chunks-cjs/behavior.core.cjs.map +1 -1
- package/lib/_chunks-cjs/behavior.markdown.cjs.map +1 -1
- package/lib/_chunks-cjs/editor-provider.cjs +379 -326
- package/lib/_chunks-cjs/editor-provider.cjs.map +1 -1
- package/lib/_chunks-cjs/parse-blocks.cjs +4 -4
- package/lib/_chunks-cjs/parse-blocks.cjs.map +1 -1
- package/lib/_chunks-cjs/selector.is-overlapping-selection.cjs.map +1 -1
- package/lib/_chunks-es/behavior.core.js +7 -7
- package/lib/_chunks-es/behavior.core.js.map +1 -1
- package/lib/_chunks-es/behavior.markdown.js.map +1 -1
- package/lib/_chunks-es/editor-provider.js +380 -327
- package/lib/_chunks-es/editor-provider.js.map +1 -1
- package/lib/_chunks-es/parse-blocks.js +4 -4
- package/lib/_chunks-es/parse-blocks.js.map +1 -1
- package/lib/_chunks-es/selector.is-overlapping-selection.js.map +1 -1
- package/lib/behaviors/index.cjs.map +1 -1
- package/lib/behaviors/index.d.cts +70 -28
- package/lib/behaviors/index.d.ts +70 -28
- package/lib/behaviors/index.js.map +1 -1
- package/lib/index.cjs +12 -14
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +61 -3
- package/lib/index.d.ts +61 -3
- package/lib/index.js +12 -14
- package/lib/index.js.map +1 -1
- package/lib/plugins/index.cjs.map +1 -1
- package/lib/plugins/index.d.cts +68 -23
- package/lib/plugins/index.d.ts +68 -23
- package/lib/plugins/index.js.map +1 -1
- package/lib/selectors/index.d.cts +69 -27
- package/lib/selectors/index.d.ts +69 -27
- package/lib/utils/index.d.cts +74 -29
- package/lib/utils/index.d.ts +74 -29
- package/package.json +6 -6
- package/src/behavior-actions/behavior.action.insert.block.ts +1 -1
- package/src/behavior-actions/behavior.action.split.block.ts +1 -1
- package/src/behavior-actions/behavior.guards.ts +1 -1
- package/src/behaviors/behavior.core.decorators.ts +4 -4
- package/src/behaviors/behavior.core.insert-break.ts +4 -4
- package/src/behaviors/behavior.decorator-pair.ts +1 -1
- package/src/behaviors/behavior.links.ts +1 -1
- package/src/behaviors/behavior.markdown.ts +1 -1
- package/src/behaviors/behavior.perform-event.ts +1 -1
- package/src/converters/converter.portable-text.deserialize.test.ts +2 -3
- package/src/converters/converter.text-html.deserialize.test.ts +62 -5
- package/src/converters/converter.text-html.serialize.test.ts +9 -5
- package/src/converters/converter.text-html.ts +66 -64
- package/src/converters/converter.text-plain.test.ts +9 -4
- package/src/converters/converter.text-plain.ts +91 -87
- package/src/converters/converters.core.ts +13 -8
- package/src/editor/Editable.tsx +18 -13
- package/src/editor/PortableTextEditor.tsx +5 -5
- package/src/editor/__tests__/PortableTextEditorTester.tsx +4 -3
- package/src/editor/__tests__/insert-block.test.tsx +10 -10
- package/src/editor/__tests__/self-solving.test.tsx +2 -2
- package/src/editor/components/Synchronizer.tsx +1 -1
- package/src/editor/create-editor.ts +51 -18
- package/src/editor/editor-machine.ts +1 -1
- package/src/editor/{define-schema.ts → editor-schema.ts} +114 -5
- package/src/editor/editor-snapshot.ts +1 -1
- package/src/editor/get-active-decorators.ts +2 -2
- package/src/editor/{create-editor-schema.ts → legacy-schema.ts} +3 -3
- package/src/editor/mutation-machine.ts +1 -1
- package/src/editor/plugins/createWithObjectKeys.ts +6 -9
- package/src/editor/plugins/createWithPatches.ts +12 -11
- package/src/editor/plugins/createWithPortableTextBlockStyle.ts +2 -6
- package/src/editor/plugins/createWithPortableTextMarkModel.ts +15 -12
- package/src/editor/plugins/createWithSchemaTypes.ts +24 -16
- package/src/editor/plugins/createWithUndoRedo.ts +3 -4
- package/src/editor/plugins/createWithUtils.ts +12 -10
- package/src/editor/plugins/with-plugins.ts +5 -15
- package/src/editor/range-decorations-machine.ts +1 -1
- package/src/editor/sync-machine.ts +1 -1
- package/src/index.ts +2 -2
- package/src/internal-utils/__tests__/operationToPatches.test.ts +12 -10
- package/src/internal-utils/__tests__/patchToOperations.test.ts +3 -2
- package/src/internal-utils/__tests__/values.test.ts +3 -2
- package/src/internal-utils/applyPatch.ts +7 -9
- package/src/internal-utils/create-test-snapshot.ts +1 -1
- package/src/internal-utils/drag-selection.test.ts +1 -1
- package/src/internal-utils/operationToPatches.ts +4 -6
- package/src/internal-utils/parse-blocks.test.ts +1 -1
- package/src/internal-utils/parse-blocks.ts +8 -7
- package/src/internal-utils/slate-children-to-blocks.ts +1 -1
- package/src/internal-utils/slate-utils.ts +1 -1
- package/src/internal-utils/validateValue.ts +4 -6
- package/src/internal-utils/values.ts +5 -5
- package/src/plugins/plugin.decorator-shortcut.ts +1 -1
- package/src/plugins/plugin.markdown.test.tsx +1 -1
- package/src/plugins/plugin.markdown.tsx +1 -1
- package/src/selectors/selector.get-selection-text.test.ts +1 -1
- package/src/selectors/selector.get-trimmed-selection.test.ts +1 -1
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import type {PortableTextBlock, PortableTextTextBlock} from '@sanity/types'
|
|
2
2
|
import {expect, test} from 'vitest'
|
|
3
3
|
import type {EditorSelection} from '..'
|
|
4
|
+
import {schemaType} from '../editor/__tests__/PortableTextEditorTester'
|
|
4
5
|
import {
|
|
5
6
|
compileSchemaDefinition,
|
|
6
7
|
defineSchema,
|
|
7
8
|
type SchemaDefinition,
|
|
8
|
-
} from '../editor/
|
|
9
|
+
} from '../editor/editor-schema'
|
|
10
|
+
import {createLegacySchema} from '../editor/legacy-schema'
|
|
9
11
|
import {createTestSnapshot} from '../internal-utils/create-test-snapshot'
|
|
10
|
-
import {
|
|
11
|
-
import {coreConverters} from './converters.core'
|
|
12
|
+
import {createConverterTextPlain} from './converter.text-plain'
|
|
12
13
|
|
|
13
14
|
const b1: PortableTextTextBlock = {
|
|
14
15
|
_type: 'block',
|
|
@@ -74,7 +75,7 @@ function createSnapshot({
|
|
|
74
75
|
}) {
|
|
75
76
|
return createTestSnapshot({
|
|
76
77
|
context: {
|
|
77
|
-
converters:
|
|
78
|
+
converters: [],
|
|
78
79
|
schema: compileSchemaDefinition(schema),
|
|
79
80
|
selection,
|
|
80
81
|
value: [b1, b2, b3, b4],
|
|
@@ -82,6 +83,10 @@ function createSnapshot({
|
|
|
82
83
|
})
|
|
83
84
|
}
|
|
84
85
|
|
|
86
|
+
const converterTextPlain = createConverterTextPlain(
|
|
87
|
+
createLegacySchema(schemaType),
|
|
88
|
+
)
|
|
89
|
+
|
|
85
90
|
test(converterTextPlain.serialize.name, () => {
|
|
86
91
|
expect(
|
|
87
92
|
converterTextPlain.serialize({
|
|
@@ -1,112 +1,116 @@
|
|
|
1
1
|
import {htmlToBlocks} from '@portabletext/block-tools'
|
|
2
2
|
import {isPortableTextTextBlock, type PortableTextBlock} from '@sanity/types'
|
|
3
3
|
import {parseBlock} from '../internal-utils/parse-blocks'
|
|
4
|
+
import type {PortableTextMemberSchemaTypes} from '../types/editor'
|
|
4
5
|
import {sliceBlocks} from '../utils'
|
|
5
6
|
import {defineConverter} from './converter.types'
|
|
6
7
|
|
|
7
|
-
export
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
export function createConverterTextPlain(
|
|
9
|
+
legacySchema: PortableTextMemberSchemaTypes,
|
|
10
|
+
) {
|
|
11
|
+
return defineConverter({
|
|
12
|
+
mimeType: 'text/plain',
|
|
13
|
+
serialize: ({snapshot, event}) => {
|
|
14
|
+
const selection =
|
|
15
|
+
snapshot.beta.internalDrag?.origin.selection ??
|
|
16
|
+
snapshot.context.selection
|
|
12
17
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
if (!selection) {
|
|
19
|
+
return {
|
|
20
|
+
type: 'serialization.failure',
|
|
21
|
+
mimeType: 'text/plain',
|
|
22
|
+
originEvent: event.originEvent,
|
|
23
|
+
reason: 'No selection',
|
|
24
|
+
}
|
|
19
25
|
}
|
|
20
|
-
}
|
|
21
26
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
27
|
+
const blocks = sliceBlocks({
|
|
28
|
+
blocks: snapshot.context.value,
|
|
29
|
+
selection,
|
|
30
|
+
})
|
|
26
31
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
const data = blocks
|
|
33
|
+
.map((block) => {
|
|
34
|
+
if (isPortableTextTextBlock(block)) {
|
|
35
|
+
return block.children
|
|
36
|
+
.map((child) => {
|
|
37
|
+
if (child._type === snapshot.context.schema.span.name) {
|
|
38
|
+
return child.text
|
|
39
|
+
}
|
|
35
40
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
return snapshot.beta.hasTag('dragging internally')
|
|
42
|
+
? `[${
|
|
43
|
+
snapshot.context.schema.inlineObjects.find(
|
|
44
|
+
(inlineObjectType) =>
|
|
45
|
+
inlineObjectType.name === child._type,
|
|
46
|
+
)?.title ?? 'Object'
|
|
47
|
+
}]`
|
|
48
|
+
: ''
|
|
49
|
+
})
|
|
50
|
+
.join('')
|
|
51
|
+
}
|
|
47
52
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
return snapshot.beta.hasTag('dragging internally')
|
|
54
|
+
? `[${
|
|
55
|
+
snapshot.context.schema.blockObjects.find(
|
|
56
|
+
(blockObjectType) => blockObjectType.name === block._type,
|
|
57
|
+
)?.title ?? 'Object'
|
|
58
|
+
}]`
|
|
59
|
+
: ''
|
|
60
|
+
})
|
|
61
|
+
.filter((block) => block !== '')
|
|
62
|
+
.join('\n\n')
|
|
58
63
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
64
|
+
return {
|
|
65
|
+
type: 'serialization.success',
|
|
66
|
+
data,
|
|
67
|
+
mimeType: 'text/plain',
|
|
68
|
+
originEvent: event.originEvent,
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
deserialize: ({snapshot, event}) => {
|
|
72
|
+
const html = escapeHtml(event.data)
|
|
73
|
+
.split(/\n{2,}/)
|
|
74
|
+
.map((line) =>
|
|
75
|
+
line
|
|
76
|
+
? `<p>${line.replace(/(?:\r\n|\r|\n)/g, '<br/>')}</p>`
|
|
77
|
+
: '<p></p>',
|
|
78
|
+
)
|
|
79
|
+
.join('')
|
|
73
80
|
|
|
74
|
-
|
|
81
|
+
const textToHtml = `<html><body>${html}</body></html>`
|
|
75
82
|
|
|
76
|
-
|
|
77
|
-
textToHtml,
|
|
78
|
-
snapshot.context.schema.portableText,
|
|
79
|
-
{
|
|
83
|
+
const blocks = htmlToBlocks(textToHtml, legacySchema.portableText, {
|
|
80
84
|
keyGenerator: snapshot.context.keyGenerator,
|
|
81
|
-
}
|
|
82
|
-
) as Array<PortableTextBlock>
|
|
85
|
+
}) as Array<PortableTextBlock>
|
|
83
86
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
const parsedBlocks = blocks.flatMap((block) => {
|
|
88
|
+
const parsedBlock = parseBlock({
|
|
89
|
+
context: snapshot.context,
|
|
90
|
+
block,
|
|
91
|
+
options: {
|
|
92
|
+
refreshKeys: false,
|
|
93
|
+
},
|
|
94
|
+
})
|
|
95
|
+
return parsedBlock ? [parsedBlock] : []
|
|
91
96
|
})
|
|
92
|
-
return parsedBlock ? [parsedBlock] : []
|
|
93
|
-
})
|
|
94
97
|
|
|
95
|
-
|
|
98
|
+
if (parsedBlocks.length === 0) {
|
|
99
|
+
return {
|
|
100
|
+
type: 'deserialization.failure',
|
|
101
|
+
mimeType: 'text/plain',
|
|
102
|
+
reason: 'No blocks deserialized',
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
96
106
|
return {
|
|
97
|
-
type: 'deserialization.
|
|
107
|
+
type: 'deserialization.success',
|
|
108
|
+
data: parsedBlocks,
|
|
98
109
|
mimeType: 'text/plain',
|
|
99
|
-
reason: 'No blocks deserialized',
|
|
100
110
|
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
type: 'deserialization.success',
|
|
105
|
-
data: parsedBlocks,
|
|
106
|
-
mimeType: 'text/plain',
|
|
107
|
-
}
|
|
108
|
-
},
|
|
109
|
-
})
|
|
111
|
+
},
|
|
112
|
+
})
|
|
113
|
+
}
|
|
110
114
|
|
|
111
115
|
const entityMap: Record<string, string> = {
|
|
112
116
|
'&': '&',
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
+
import type {PortableTextMemberSchemaTypes} from '../types/editor'
|
|
1
2
|
import {converterJson} from './converter.json'
|
|
2
3
|
import {converterPortableText} from './converter.portable-text'
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
4
|
+
import {createConverterTextHtml} from './converter.text-html'
|
|
5
|
+
import {createConverterTextPlain} from './converter.text-plain'
|
|
5
6
|
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
export function createCoreConverters(
|
|
8
|
+
legacySchema: PortableTextMemberSchemaTypes,
|
|
9
|
+
) {
|
|
10
|
+
return [
|
|
11
|
+
converterJson,
|
|
12
|
+
converterPortableText,
|
|
13
|
+
createConverterTextHtml(legacySchema),
|
|
14
|
+
createConverterTextPlain(legacySchema),
|
|
15
|
+
]
|
|
16
|
+
}
|
package/src/editor/Editable.tsx
CHANGED
|
@@ -170,14 +170,13 @@ export const PortableTextEditable = forwardRef<
|
|
|
170
170
|
const readOnly = useSelector(editorActor, (s) =>
|
|
171
171
|
s.matches({'edit mode': 'read only'}),
|
|
172
172
|
)
|
|
173
|
-
const schemaTypes = useSelector(editorActor, (s) => s.context.schema)
|
|
174
173
|
const slateEditor = useSlate()
|
|
175
174
|
|
|
176
175
|
const rangeDecorationsActor = useActorRef(rangeDecorationsMachine, {
|
|
177
176
|
input: {
|
|
178
177
|
rangeDecorations: rangeDecorations ?? [],
|
|
179
178
|
readOnly,
|
|
180
|
-
schema:
|
|
179
|
+
schema: editorActor.getSnapshot().context.schema,
|
|
181
180
|
slateEditor,
|
|
182
181
|
skipSetup: !editorActor.getSnapshot().matches({setup: 'setting up'}),
|
|
183
182
|
},
|
|
@@ -202,8 +201,6 @@ export const PortableTextEditable = forwardRef<
|
|
|
202
201
|
})
|
|
203
202
|
}, [rangeDecorationsActor, rangeDecorations])
|
|
204
203
|
|
|
205
|
-
const blockTypeName = schemaTypes.block.name
|
|
206
|
-
|
|
207
204
|
// Output a minimal React editor inside Editable when in readOnly mode.
|
|
208
205
|
// NOTE: make sure all the plugins used here can be safely run over again at any point.
|
|
209
206
|
// There will be a problem if they redefine editor methods and then calling the original method within themselves.
|
|
@@ -232,12 +229,12 @@ export const PortableTextEditable = forwardRef<
|
|
|
232
229
|
renderChild={renderChild}
|
|
233
230
|
renderListItem={renderListItem}
|
|
234
231
|
renderStyle={renderStyle}
|
|
235
|
-
schemaTypes={schemaTypes}
|
|
232
|
+
schemaTypes={portableTextEditor.schemaTypes}
|
|
236
233
|
spellCheck={spellCheck}
|
|
237
234
|
/>
|
|
238
235
|
),
|
|
239
236
|
[
|
|
240
|
-
|
|
237
|
+
portableTextEditor,
|
|
241
238
|
spellCheck,
|
|
242
239
|
readOnly,
|
|
243
240
|
renderBlock,
|
|
@@ -258,7 +255,7 @@ export const PortableTextEditable = forwardRef<
|
|
|
258
255
|
<Leaf
|
|
259
256
|
{...lProps}
|
|
260
257
|
editorActor={editorActor}
|
|
261
|
-
schemaTypes={schemaTypes}
|
|
258
|
+
schemaTypes={portableTextEditor.schemaTypes}
|
|
262
259
|
renderAnnotation={renderAnnotation}
|
|
263
260
|
renderChild={renderChild}
|
|
264
261
|
renderDecorator={renderDecorator}
|
|
@@ -289,12 +286,12 @@ export const PortableTextEditable = forwardRef<
|
|
|
289
286
|
},
|
|
290
287
|
[
|
|
291
288
|
editorActor,
|
|
289
|
+
portableTextEditor,
|
|
292
290
|
readOnly,
|
|
293
291
|
renderAnnotation,
|
|
294
292
|
renderChild,
|
|
295
293
|
renderDecorator,
|
|
296
294
|
renderPlaceholder,
|
|
297
|
-
schemaTypes,
|
|
298
295
|
],
|
|
299
296
|
)
|
|
300
297
|
|
|
@@ -303,7 +300,10 @@ export const PortableTextEditable = forwardRef<
|
|
|
303
300
|
debug(`Selection from props ${JSON.stringify(propsSelection)}`)
|
|
304
301
|
const normalizedSelection = normalizeSelection(
|
|
305
302
|
propsSelection,
|
|
306
|
-
fromSlateValue(
|
|
303
|
+
fromSlateValue(
|
|
304
|
+
slateEditor.children,
|
|
305
|
+
editorActor.getSnapshot().context.schema.block.name,
|
|
306
|
+
),
|
|
307
307
|
)
|
|
308
308
|
if (normalizedSelection !== null) {
|
|
309
309
|
debug(
|
|
@@ -324,7 +324,7 @@ export const PortableTextEditable = forwardRef<
|
|
|
324
324
|
}
|
|
325
325
|
}
|
|
326
326
|
}
|
|
327
|
-
}, [
|
|
327
|
+
}, [editorActor, propsSelection, slateEditor])
|
|
328
328
|
|
|
329
329
|
// Restore selection from props when the editor has been initialized properly with it's value
|
|
330
330
|
useEffect(() => {
|
|
@@ -447,13 +447,18 @@ export const PortableTextEditable = forwardRef<
|
|
|
447
447
|
const value = PortableTextEditor.getValue(portableTextEditor)
|
|
448
448
|
const ptRange = slateEditor.selection
|
|
449
449
|
? slateRangeToSelection({
|
|
450
|
-
schema:
|
|
450
|
+
schema: editorActor.getSnapshot().context.schema,
|
|
451
451
|
editor: slateEditor,
|
|
452
452
|
range: slateEditor.selection,
|
|
453
453
|
})
|
|
454
454
|
: null
|
|
455
455
|
const path = ptRange?.focus.path || []
|
|
456
|
-
const onPasteResult = onPaste?.({
|
|
456
|
+
const onPasteResult = onPaste?.({
|
|
457
|
+
event,
|
|
458
|
+
value,
|
|
459
|
+
path,
|
|
460
|
+
schemaTypes: portableTextEditor.schemaTypes,
|
|
461
|
+
})
|
|
457
462
|
|
|
458
463
|
if (onPasteResult || !slateEditor.selection) {
|
|
459
464
|
event.preventDefault()
|
|
@@ -552,7 +557,7 @@ export const PortableTextEditable = forwardRef<
|
|
|
552
557
|
|
|
553
558
|
debug('No result from custom paste handler, pasting normally')
|
|
554
559
|
},
|
|
555
|
-
[editorActor, onPaste, portableTextEditor,
|
|
560
|
+
[editorActor, onPaste, portableTextEditor, slateEditor],
|
|
556
561
|
)
|
|
557
562
|
|
|
558
563
|
const handleOnFocus: FocusEventHandler<HTMLDivElement> = useCallback(
|
|
@@ -29,12 +29,13 @@ import type {
|
|
|
29
29
|
} from '../types/editor'
|
|
30
30
|
import {Synchronizer} from './components/Synchronizer'
|
|
31
31
|
import {createInternalEditor, type InternalEditor} from './create-editor'
|
|
32
|
-
import {createEditorSchema} from './create-editor-schema'
|
|
33
32
|
import {EditorActorContext} from './editor-actor-context'
|
|
34
33
|
import type {EditorActor} from './editor-machine'
|
|
34
|
+
import {legacySchemaToEditorSchema} from './editor-schema'
|
|
35
35
|
import {PortableTextEditorContext} from './hooks/usePortableTextEditor'
|
|
36
36
|
import {PortableTextEditorSelectionProvider} from './hooks/usePortableTextEditorSelection'
|
|
37
37
|
import {defaultKeyGenerator} from './key-generator'
|
|
38
|
+
import {createLegacySchema} from './legacy-schema'
|
|
38
39
|
|
|
39
40
|
const debug = debugWithName('component:PortableTextEditor')
|
|
40
41
|
|
|
@@ -148,8 +149,7 @@ export class PortableTextEditor extends Component<
|
|
|
148
149
|
})
|
|
149
150
|
}
|
|
150
151
|
|
|
151
|
-
this.schemaTypes =
|
|
152
|
-
this.editor._internal.editorActor.getSnapshot().context.schema
|
|
152
|
+
this.schemaTypes = this.editor._internal.legacySchema
|
|
153
153
|
this.editable = this.editor._internal.editable
|
|
154
154
|
}
|
|
155
155
|
|
|
@@ -160,7 +160,7 @@ export class PortableTextEditor extends Component<
|
|
|
160
160
|
!prevProps.editor &&
|
|
161
161
|
this.props.schemaType !== prevProps.schemaType
|
|
162
162
|
) {
|
|
163
|
-
this.schemaTypes =
|
|
163
|
+
this.schemaTypes = createLegacySchema(
|
|
164
164
|
this.props.schemaType.hasOwnProperty('jsonType')
|
|
165
165
|
? this.props.schemaType
|
|
166
166
|
: compileType(this.props.schemaType),
|
|
@@ -168,7 +168,7 @@ export class PortableTextEditor extends Component<
|
|
|
168
168
|
|
|
169
169
|
this.editor._internal.editorActor.send({
|
|
170
170
|
type: 'update schema',
|
|
171
|
-
schema: this.schemaTypes,
|
|
171
|
+
schema: legacySchemaToEditorSchema(this.schemaTypes),
|
|
172
172
|
})
|
|
173
173
|
}
|
|
174
174
|
|
|
@@ -10,8 +10,9 @@ import {
|
|
|
10
10
|
} from '../../index'
|
|
11
11
|
|
|
12
12
|
const imageType = defineField({
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
name: 'custom image',
|
|
14
|
+
type: 'object',
|
|
15
|
+
fields: [],
|
|
15
16
|
})
|
|
16
17
|
|
|
17
18
|
const someObject = defineField({
|
|
@@ -68,7 +69,7 @@ const colorAndLink = defineArrayMember({
|
|
|
68
69
|
|
|
69
70
|
const schema = Schema.compile({
|
|
70
71
|
name: 'test',
|
|
71
|
-
types: [portableTextType, colorAndLink],
|
|
72
|
+
types: [portableTextType, colorAndLink, imageType],
|
|
72
73
|
})
|
|
73
74
|
|
|
74
75
|
export const PortableTextEditorTester = forwardRef(
|
|
@@ -12,9 +12,9 @@ const schema = Schema.compile({
|
|
|
12
12
|
{
|
|
13
13
|
name: 'portable-text',
|
|
14
14
|
type: 'array',
|
|
15
|
-
of: [{type: 'block'}, {type: 'image'}],
|
|
15
|
+
of: [{type: 'block'}, {type: 'custom image'}],
|
|
16
16
|
},
|
|
17
|
-
{name: 'image', type: 'object'},
|
|
17
|
+
{name: 'custom image', type: 'object'},
|
|
18
18
|
],
|
|
19
19
|
}).get('portable-text')
|
|
20
20
|
|
|
@@ -71,7 +71,7 @@ describe(PortableTextEditor.insertBlock.name, () => {
|
|
|
71
71
|
await waitFor(() => {
|
|
72
72
|
if (editorRef.current) {
|
|
73
73
|
const imageBlockType = editorRef.current.schemaTypes.blockObjects.find(
|
|
74
|
-
(object) => object.name === 'image',
|
|
74
|
+
(object) => object.name === 'custom image',
|
|
75
75
|
)!
|
|
76
76
|
PortableTextEditor.insertBlock(editorRef.current, imageBlockType)
|
|
77
77
|
}
|
|
@@ -81,7 +81,7 @@ describe(PortableTextEditor.insertBlock.name, () => {
|
|
|
81
81
|
await waitFor(() => {
|
|
82
82
|
if (editorRef.current) {
|
|
83
83
|
expect(PortableTextEditor.getValue(editorRef.current)).toEqual([
|
|
84
|
-
{_key: 'bb', _type: 'image'},
|
|
84
|
+
{_key: 'bb', _type: 'custom image'},
|
|
85
85
|
])
|
|
86
86
|
}
|
|
87
87
|
})
|
|
@@ -140,7 +140,7 @@ describe(PortableTextEditor.insertBlock.name, () => {
|
|
|
140
140
|
await waitFor(() => {
|
|
141
141
|
if (editorRef.current) {
|
|
142
142
|
const imageBlockType = editorRef.current.schemaTypes.blockObjects.find(
|
|
143
|
-
(object) => object.name === 'image',
|
|
143
|
+
(object) => object.name === 'custom image',
|
|
144
144
|
)!
|
|
145
145
|
PortableTextEditor.insertBlock(editorRef.current, imageBlockType)
|
|
146
146
|
}
|
|
@@ -151,7 +151,7 @@ describe(PortableTextEditor.insertBlock.name, () => {
|
|
|
151
151
|
if (editorRef.current) {
|
|
152
152
|
expect(PortableTextEditor.getValue(editorRef.current)).toEqual([
|
|
153
153
|
nonEmptyTextBlock,
|
|
154
|
-
{_key: 'bb', _type: 'image'},
|
|
154
|
+
{_key: 'bb', _type: 'custom image'},
|
|
155
155
|
])
|
|
156
156
|
}
|
|
157
157
|
})
|
|
@@ -174,7 +174,7 @@ describe(PortableTextEditor.insertBlock.name, () => {
|
|
|
174
174
|
}
|
|
175
175
|
const imageBlock: PortableTextBlock = {
|
|
176
176
|
_key: 'bb',
|
|
177
|
-
_type: 'image',
|
|
177
|
+
_type: 'custom image',
|
|
178
178
|
}
|
|
179
179
|
const initialValue: Array<PortableTextBlock> = [emptyTextBlock, imageBlock]
|
|
180
180
|
const onChange: (change: EditorChange) => void = vi.fn()
|
|
@@ -226,7 +226,7 @@ describe(PortableTextEditor.insertBlock.name, () => {
|
|
|
226
226
|
await waitFor(() => {
|
|
227
227
|
if (editorRef.current) {
|
|
228
228
|
const imageBlockType = editorRef.current.schemaTypes.blockObjects.find(
|
|
229
|
-
(object) => object.name === 'image',
|
|
229
|
+
(object) => object.name === 'custom image',
|
|
230
230
|
)!
|
|
231
231
|
PortableTextEditor.insertBlock(editorRef.current, imageBlockType)
|
|
232
232
|
}
|
|
@@ -236,8 +236,8 @@ describe(PortableTextEditor.insertBlock.name, () => {
|
|
|
236
236
|
await waitFor(() => {
|
|
237
237
|
if (editorRef.current) {
|
|
238
238
|
expect(PortableTextEditor.getValue(editorRef.current)).toEqual([
|
|
239
|
-
{_key: 'bc', _type: 'image'},
|
|
240
|
-
{_key: 'bb', _type: 'image'},
|
|
239
|
+
{_key: 'bc', _type: 'custom image'},
|
|
240
|
+
{_key: 'bb', _type: 'custom image'},
|
|
241
241
|
])
|
|
242
242
|
}
|
|
243
243
|
})
|
|
@@ -13,9 +13,9 @@ const schema = Schema.compile({
|
|
|
13
13
|
{
|
|
14
14
|
name: 'portable-text',
|
|
15
15
|
type: 'array',
|
|
16
|
-
of: [{type: 'block'}, {type: 'image'}],
|
|
16
|
+
of: [{type: 'block'}, {type: 'custom image'}],
|
|
17
17
|
},
|
|
18
|
-
{name: 'image', type: 'object'},
|
|
18
|
+
{name: 'custom image', type: 'object'},
|
|
19
19
|
],
|
|
20
20
|
}).get('portable-text')
|
|
21
21
|
type OnChange = ComponentProps<typeof PortableTextEditor>['onChange']
|
|
@@ -44,7 +44,7 @@ export function Synchronizer(props: SynchronizerProps) {
|
|
|
44
44
|
})
|
|
45
45
|
const mutationActorRef = useActorRef(mutationMachine, {
|
|
46
46
|
input: {
|
|
47
|
-
schema: editorActor.getSnapshot().context.schema,
|
|
47
|
+
schema: props.editorActor.getSnapshot().context.schema,
|
|
48
48
|
slateEditor,
|
|
49
49
|
},
|
|
50
50
|
})
|
|
@@ -13,21 +13,26 @@ import {
|
|
|
13
13
|
} from 'xstate'
|
|
14
14
|
import type {Behavior} from '../behaviors/behavior.types.behavior'
|
|
15
15
|
import type {ExternalBehaviorEvent} from '../behaviors/behavior.types.event'
|
|
16
|
-
import {
|
|
16
|
+
import {createCoreConverters} from '../converters/converters.core'
|
|
17
17
|
import {compileType} from '../internal-utils/schema'
|
|
18
|
-
import type {EditableAPI} from '../types/editor'
|
|
19
|
-
import {createEditorSchema} from './create-editor-schema'
|
|
18
|
+
import type {EditableAPI, PortableTextMemberSchemaTypes} from '../types/editor'
|
|
20
19
|
import {createSlateEditor, type SlateEditor} from './create-slate-editor'
|
|
21
|
-
import {compileSchemaDefinition, type SchemaDefinition} from './define-schema'
|
|
22
20
|
import {
|
|
23
21
|
editorMachine,
|
|
24
22
|
type EditorActor,
|
|
25
23
|
type EditorEmittedEvent,
|
|
26
24
|
type ExternalEditorEvent,
|
|
27
25
|
} from './editor-machine'
|
|
26
|
+
import {
|
|
27
|
+
compileSchemaDefinitionToLegacySchema,
|
|
28
|
+
legacySchemaToEditorSchema,
|
|
29
|
+
type SchemaDefinition,
|
|
30
|
+
} from './editor-schema'
|
|
31
|
+
import type {EditorSchema} from './editor-schema'
|
|
28
32
|
import {getEditorSnapshot} from './editor-selector'
|
|
29
33
|
import type {EditorSnapshot} from './editor-snapshot'
|
|
30
34
|
import {defaultKeyGenerator} from './key-generator'
|
|
35
|
+
import {createLegacySchema} from './legacy-schema'
|
|
31
36
|
import {createEditableAPI} from './plugins/createWithEditableAPI'
|
|
32
37
|
|
|
33
38
|
/**
|
|
@@ -79,49 +84,76 @@ export type InternalEditor = Editor & {
|
|
|
79
84
|
editable: EditableAPI
|
|
80
85
|
editorActor: EditorActor
|
|
81
86
|
slateEditor: SlateEditor
|
|
87
|
+
legacySchema: PortableTextMemberSchemaTypes
|
|
82
88
|
}
|
|
83
89
|
}
|
|
84
90
|
|
|
85
91
|
export function createInternalEditor(config: EditorConfig): InternalEditor {
|
|
92
|
+
const legacySchema = config.schemaDefinition
|
|
93
|
+
? compileSchemaDefinitionToLegacySchema(config.schemaDefinition)
|
|
94
|
+
: createLegacySchema(
|
|
95
|
+
config.schema.hasOwnProperty('jsonType')
|
|
96
|
+
? config.schema
|
|
97
|
+
: compileType(config.schema),
|
|
98
|
+
)
|
|
99
|
+
const editorSchema = legacySchemaToEditorSchema(legacySchema)
|
|
100
|
+
|
|
86
101
|
const editorActor = createActor(editorMachine, {
|
|
87
|
-
input: editorConfigToMachineInput(
|
|
102
|
+
input: editorConfigToMachineInput({
|
|
103
|
+
...config,
|
|
104
|
+
schema: editorSchema,
|
|
105
|
+
legacySchema,
|
|
106
|
+
}),
|
|
88
107
|
})
|
|
89
108
|
editorActor.start()
|
|
90
109
|
|
|
91
|
-
return createInternalEditorFromActor(editorActor)
|
|
110
|
+
return createInternalEditorFromActor(editorActor, legacySchema)
|
|
92
111
|
}
|
|
93
112
|
|
|
94
113
|
export function useCreateInternalEditor(config: EditorConfig): InternalEditor {
|
|
114
|
+
const legacySchema = config.schemaDefinition
|
|
115
|
+
? compileSchemaDefinitionToLegacySchema(config.schemaDefinition)
|
|
116
|
+
: createLegacySchema(
|
|
117
|
+
config.schema.hasOwnProperty('jsonType')
|
|
118
|
+
? config.schema
|
|
119
|
+
: compileType(config.schema),
|
|
120
|
+
)
|
|
121
|
+
const editorSchema = legacySchemaToEditorSchema(legacySchema)
|
|
122
|
+
|
|
95
123
|
const editorActor = useActorRef(editorMachine, {
|
|
96
|
-
input: editorConfigToMachineInput(
|
|
124
|
+
input: editorConfigToMachineInput({
|
|
125
|
+
...config,
|
|
126
|
+
schema: editorSchema,
|
|
127
|
+
legacySchema,
|
|
128
|
+
}),
|
|
97
129
|
})
|
|
98
130
|
|
|
99
131
|
return useMemo(
|
|
100
|
-
() => createInternalEditorFromActor(editorActor),
|
|
101
|
-
[editorActor],
|
|
132
|
+
() => createInternalEditorFromActor(editorActor, legacySchema),
|
|
133
|
+
[editorActor, legacySchema],
|
|
102
134
|
)
|
|
103
135
|
}
|
|
104
136
|
|
|
105
|
-
function editorConfigToMachineInput(
|
|
137
|
+
function editorConfigToMachineInput(
|
|
138
|
+
config: Omit<EditorConfig, 'schema'> & {
|
|
139
|
+
schema: EditorSchema
|
|
140
|
+
legacySchema: PortableTextMemberSchemaTypes
|
|
141
|
+
},
|
|
142
|
+
) {
|
|
106
143
|
return {
|
|
107
144
|
behaviors: config.behaviors,
|
|
108
|
-
converters:
|
|
145
|
+
converters: createCoreConverters(config.legacySchema),
|
|
109
146
|
keyGenerator: config.keyGenerator ?? defaultKeyGenerator,
|
|
110
147
|
maxBlocks: config.maxBlocks,
|
|
111
148
|
readOnly: config.readOnly,
|
|
112
|
-
schema: config.
|
|
113
|
-
? compileSchemaDefinition(config.schemaDefinition)
|
|
114
|
-
: createEditorSchema(
|
|
115
|
-
config.schema.hasOwnProperty('jsonType')
|
|
116
|
-
? config.schema
|
|
117
|
-
: compileType(config.schema),
|
|
118
|
-
),
|
|
149
|
+
schema: config.schema,
|
|
119
150
|
initialValue: config.initialValue,
|
|
120
151
|
} as const
|
|
121
152
|
}
|
|
122
153
|
|
|
123
154
|
function createInternalEditorFromActor(
|
|
124
155
|
editorActor: EditorActor,
|
|
156
|
+
legacySchema: PortableTextMemberSchemaTypes,
|
|
125
157
|
): InternalEditor {
|
|
126
158
|
const slateEditor = createSlateEditor({editorActor})
|
|
127
159
|
const editable = createEditableAPI(slateEditor.instance, editorActor)
|
|
@@ -208,6 +240,7 @@ function createInternalEditorFromActor(
|
|
|
208
240
|
_internal: {
|
|
209
241
|
editable,
|
|
210
242
|
editorActor,
|
|
243
|
+
legacySchema,
|
|
211
244
|
slateEditor,
|
|
212
245
|
},
|
|
213
246
|
}
|