@portabletext/editor 1.46.0 → 1.47.1
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 +411 -327
- 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 +412 -328
- 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 +590 -28
- package/lib/behaviors/index.d.ts +590 -28
- package/lib/behaviors/index.js.map +1 -1
- package/lib/index.cjs +4 -4
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +71 -3
- package/lib/index.d.ts +71 -3
- package/lib/index.js +4 -4
- package/lib/index.js.map +1 -1
- package/lib/plugins/index.cjs.map +1 -1
- package/lib/plugins/index.d.cts +78 -23
- package/lib/plugins/index.d.ts +78 -23
- package/lib/plugins/index.js.map +1 -1
- package/lib/selectors/index.d.cts +79 -27
- package/lib/selectors/index.d.ts +79 -27
- package/lib/utils/index.d.cts +84 -29
- package/lib/utils/index.d.ts +84 -29
- package/package.json +6 -6
- package/src/behavior-actions/behavior.action.insert.block.ts +1 -1
- package/src/behavior-actions/behavior.action.move.backward.ts +12 -0
- package/src/behavior-actions/behavior.action.move.forward.ts +11 -0
- package/src/behavior-actions/behavior.action.split.block.ts +1 -1
- package/src/behavior-actions/behavior.actions.ts +18 -0
- 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/behaviors/behavior.types.event.ts +10 -0
- 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 +10 -5
- 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,17 +1,17 @@
|
|
|
1
1
|
import {describe, expect, test} from 'vitest'
|
|
2
2
|
import {
|
|
3
3
|
compileSchemaDefinition,
|
|
4
|
+
compileSchemaDefinitionToLegacySchema,
|
|
4
5
|
defineSchema,
|
|
5
6
|
type SchemaDefinition,
|
|
6
|
-
} from '../editor/
|
|
7
|
+
} from '../editor/editor-schema'
|
|
7
8
|
import {createTestSnapshot} from '../internal-utils/create-test-snapshot'
|
|
8
|
-
import {
|
|
9
|
-
import {coreConverters} from './converters.core'
|
|
9
|
+
import {createConverterTextHtml} from './converter.text-html'
|
|
10
10
|
|
|
11
11
|
function createSnapshot(schema: SchemaDefinition) {
|
|
12
12
|
return createTestSnapshot({
|
|
13
13
|
context: {
|
|
14
|
-
converters:
|
|
14
|
+
converters: [],
|
|
15
15
|
schema: compileSchemaDefinition(schema),
|
|
16
16
|
},
|
|
17
17
|
})
|
|
@@ -25,8 +25,12 @@ const unorderedList = '<ul><li>foo</li><li>bar</li></ul>'
|
|
|
25
25
|
const orderedList = '<ol><li>foo</li><li>bar</li></ol>'
|
|
26
26
|
const nestedList = '<ol><li>foo<ul><li>bar</li></ul></li></ol>'
|
|
27
27
|
|
|
28
|
-
describe(
|
|
28
|
+
describe(createConverterTextHtml.name, () => {
|
|
29
29
|
test('paragraph with unknown decorators', () => {
|
|
30
|
+
const converterTextHtml = createConverterTextHtml(
|
|
31
|
+
compileSchemaDefinitionToLegacySchema(defineSchema({})),
|
|
32
|
+
)
|
|
33
|
+
|
|
30
34
|
expect(
|
|
31
35
|
converterTextHtml.deserialize({
|
|
32
36
|
snapshot: createSnapshot(defineSchema({})),
|
|
@@ -56,6 +60,14 @@ describe(converterTextHtml.deserialize.name, () => {
|
|
|
56
60
|
})
|
|
57
61
|
|
|
58
62
|
test('paragraph with known decorators', () => {
|
|
63
|
+
const converterTextHtml = createConverterTextHtml(
|
|
64
|
+
compileSchemaDefinitionToLegacySchema(
|
|
65
|
+
defineSchema({
|
|
66
|
+
decorators: [{name: 'strong'}, {name: 'em'}, {name: 'code'}],
|
|
67
|
+
}),
|
|
68
|
+
),
|
|
69
|
+
)
|
|
70
|
+
|
|
59
71
|
expect(
|
|
60
72
|
converterTextHtml.deserialize({
|
|
61
73
|
snapshot: createSnapshot(
|
|
@@ -101,6 +113,13 @@ describe(converterTextHtml.deserialize.name, () => {
|
|
|
101
113
|
})
|
|
102
114
|
|
|
103
115
|
test('image', () => {
|
|
116
|
+
const converterTextHtml = createConverterTextHtml(
|
|
117
|
+
compileSchemaDefinitionToLegacySchema(
|
|
118
|
+
defineSchema({
|
|
119
|
+
blockObjects: [{name: 'image'}],
|
|
120
|
+
}),
|
|
121
|
+
),
|
|
122
|
+
)
|
|
104
123
|
expect(
|
|
105
124
|
converterTextHtml.deserialize({
|
|
106
125
|
snapshot: createSnapshot(
|
|
@@ -119,6 +138,10 @@ describe(converterTextHtml.deserialize.name, () => {
|
|
|
119
138
|
})
|
|
120
139
|
|
|
121
140
|
test('paragraph with unknown link', () => {
|
|
141
|
+
const converterTextHtml = createConverterTextHtml(
|
|
142
|
+
compileSchemaDefinitionToLegacySchema(defineSchema({})),
|
|
143
|
+
)
|
|
144
|
+
|
|
122
145
|
expect(
|
|
123
146
|
converterTextHtml.deserialize({
|
|
124
147
|
snapshot: createSnapshot(defineSchema({})),
|
|
@@ -148,6 +171,16 @@ describe(converterTextHtml.deserialize.name, () => {
|
|
|
148
171
|
})
|
|
149
172
|
|
|
150
173
|
test('paragraph with known link', () => {
|
|
174
|
+
const converterTextHtml = createConverterTextHtml(
|
|
175
|
+
compileSchemaDefinitionToLegacySchema(
|
|
176
|
+
defineSchema({
|
|
177
|
+
annotations: [
|
|
178
|
+
{name: 'link', fields: [{name: 'href', type: 'string'}]},
|
|
179
|
+
],
|
|
180
|
+
}),
|
|
181
|
+
),
|
|
182
|
+
)
|
|
183
|
+
|
|
151
184
|
expect(
|
|
152
185
|
converterTextHtml.deserialize({
|
|
153
186
|
snapshot: createSnapshot(
|
|
@@ -195,6 +228,14 @@ describe(converterTextHtml.deserialize.name, () => {
|
|
|
195
228
|
})
|
|
196
229
|
|
|
197
230
|
test('unordered list', () => {
|
|
231
|
+
const converterTextHtml = createConverterTextHtml(
|
|
232
|
+
compileSchemaDefinitionToLegacySchema(
|
|
233
|
+
defineSchema({
|
|
234
|
+
lists: [{name: 'bullet'}],
|
|
235
|
+
}),
|
|
236
|
+
),
|
|
237
|
+
)
|
|
238
|
+
|
|
198
239
|
expect(
|
|
199
240
|
converterTextHtml.deserialize({
|
|
200
241
|
snapshot: createSnapshot(
|
|
@@ -246,6 +287,14 @@ describe(converterTextHtml.deserialize.name, () => {
|
|
|
246
287
|
})
|
|
247
288
|
|
|
248
289
|
test('ordered list', () => {
|
|
290
|
+
const converterTextHtml = createConverterTextHtml(
|
|
291
|
+
compileSchemaDefinitionToLegacySchema(
|
|
292
|
+
defineSchema({
|
|
293
|
+
lists: [{name: 'number'}],
|
|
294
|
+
}),
|
|
295
|
+
),
|
|
296
|
+
)
|
|
297
|
+
|
|
249
298
|
expect(
|
|
250
299
|
converterTextHtml.deserialize({
|
|
251
300
|
snapshot: createSnapshot(
|
|
@@ -297,6 +346,14 @@ describe(converterTextHtml.deserialize.name, () => {
|
|
|
297
346
|
})
|
|
298
347
|
|
|
299
348
|
test('nested list', () => {
|
|
349
|
+
const converterTextHtml = createConverterTextHtml(
|
|
350
|
+
compileSchemaDefinitionToLegacySchema(
|
|
351
|
+
defineSchema({
|
|
352
|
+
lists: [{name: 'bullet'}, {name: 'number'}],
|
|
353
|
+
}),
|
|
354
|
+
),
|
|
355
|
+
)
|
|
356
|
+
|
|
300
357
|
expect(
|
|
301
358
|
converterTextHtml.deserialize({
|
|
302
359
|
snapshot: createSnapshot(
|
|
@@ -3,12 +3,12 @@ import {describe, expect, test} from 'vitest'
|
|
|
3
3
|
import type {EditorSelection} from '..'
|
|
4
4
|
import {
|
|
5
5
|
compileSchemaDefinition,
|
|
6
|
+
compileSchemaDefinitionToLegacySchema,
|
|
6
7
|
defineSchema,
|
|
7
8
|
type SchemaDefinition,
|
|
8
|
-
} from '../editor/
|
|
9
|
+
} from '../editor/editor-schema'
|
|
9
10
|
import {createTestSnapshot} from '../internal-utils/create-test-snapshot'
|
|
10
|
-
import {
|
|
11
|
-
import {coreConverters} from './converters.core'
|
|
11
|
+
import {createConverterTextHtml} from './converter.text-html'
|
|
12
12
|
|
|
13
13
|
const decoratedParagraph: PortableTextTextBlock = {
|
|
14
14
|
_key: 'k0',
|
|
@@ -78,7 +78,7 @@ const paragraphWithInlineBlock: PortableTextTextBlock = {
|
|
|
78
78
|
function createSnapshot(schema: SchemaDefinition, selection: EditorSelection) {
|
|
79
79
|
return createTestSnapshot({
|
|
80
80
|
context: {
|
|
81
|
-
converters:
|
|
81
|
+
converters: [],
|
|
82
82
|
schema: compileSchemaDefinition(schema),
|
|
83
83
|
selection,
|
|
84
84
|
value: [decoratedParagraph, image, b2, paragraphWithInlineBlock],
|
|
@@ -86,6 +86,10 @@ function createSnapshot(schema: SchemaDefinition, selection: EditorSelection) {
|
|
|
86
86
|
})
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
const converterTextHtml = createConverterTextHtml(
|
|
90
|
+
compileSchemaDefinitionToLegacySchema(defineSchema({})),
|
|
91
|
+
)
|
|
92
|
+
|
|
89
93
|
describe(converterTextHtml.serialize.name, () => {
|
|
90
94
|
test('paragraph with decorators', () => {
|
|
91
95
|
expect(
|
|
@@ -177,7 +181,7 @@ describe(converterTextHtml.serialize.name, () => {
|
|
|
177
181
|
converterTextHtml.serialize({
|
|
178
182
|
snapshot: createTestSnapshot({
|
|
179
183
|
context: {
|
|
180
|
-
converters:
|
|
184
|
+
converters: [],
|
|
181
185
|
value: [
|
|
182
186
|
{
|
|
183
187
|
_key: 'k0',
|
|
@@ -2,87 +2,89 @@ import {htmlToBlocks} from '@portabletext/block-tools'
|
|
|
2
2
|
import {toHTML} from '@portabletext/to-html'
|
|
3
3
|
import type {PortableTextBlock} from '@sanity/types'
|
|
4
4
|
import {parseBlock} from '../internal-utils/parse-blocks'
|
|
5
|
+
import type {PortableTextMemberSchemaTypes} from '../types/editor'
|
|
5
6
|
import {sliceBlocks} from '../utils'
|
|
6
7
|
import {defineConverter} from './converter.types'
|
|
7
8
|
|
|
8
|
-
export
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
export function createConverterTextHtml(
|
|
10
|
+
legacySchema: PortableTextMemberSchemaTypes,
|
|
11
|
+
) {
|
|
12
|
+
return defineConverter({
|
|
13
|
+
mimeType: 'text/html',
|
|
14
|
+
serialize: ({snapshot, event}) => {
|
|
15
|
+
const selection =
|
|
16
|
+
snapshot.beta.internalDrag?.origin.selection ??
|
|
17
|
+
snapshot.context.selection
|
|
13
18
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
if (!selection) {
|
|
20
|
+
return {
|
|
21
|
+
type: 'serialization.failure',
|
|
22
|
+
mimeType: 'text/html',
|
|
23
|
+
originEvent: event.originEvent,
|
|
24
|
+
reason: 'No selection',
|
|
25
|
+
}
|
|
20
26
|
}
|
|
21
|
-
}
|
|
22
27
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
const blocks = sliceBlocks({
|
|
29
|
+
blocks: snapshot.context.value,
|
|
30
|
+
selection,
|
|
31
|
+
})
|
|
27
32
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
const html = toHTML(blocks, {
|
|
34
|
+
onMissingComponent: false,
|
|
35
|
+
components: {
|
|
36
|
+
unknownType: ({children}) =>
|
|
37
|
+
children !== undefined ? `${children}` : '',
|
|
38
|
+
},
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
if (html === '') {
|
|
42
|
+
return {
|
|
43
|
+
type: 'serialization.failure',
|
|
44
|
+
mimeType: 'text/html',
|
|
45
|
+
originEvent: event.originEvent,
|
|
46
|
+
reason: 'Serialized HTML is empty',
|
|
47
|
+
}
|
|
48
|
+
}
|
|
35
49
|
|
|
36
|
-
if (html === '') {
|
|
37
50
|
return {
|
|
38
|
-
type: 'serialization.
|
|
51
|
+
type: 'serialization.success',
|
|
52
|
+
data: html,
|
|
39
53
|
mimeType: 'text/html',
|
|
40
54
|
originEvent: event.originEvent,
|
|
41
|
-
reason: 'Serialized HTML is empty',
|
|
42
55
|
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
type: 'serialization.success',
|
|
47
|
-
data: html,
|
|
48
|
-
mimeType: 'text/html',
|
|
49
|
-
originEvent: event.originEvent,
|
|
50
|
-
}
|
|
51
|
-
},
|
|
52
|
-
deserialize: ({snapshot, event}) => {
|
|
53
|
-
const blocks = htmlToBlocks(
|
|
54
|
-
event.data,
|
|
55
|
-
snapshot.context.schema.portableText,
|
|
56
|
-
{
|
|
56
|
+
},
|
|
57
|
+
deserialize: ({snapshot, event}) => {
|
|
58
|
+
const blocks = htmlToBlocks(event.data, legacySchema.portableText, {
|
|
57
59
|
keyGenerator: snapshot.context.keyGenerator,
|
|
58
60
|
unstable_whitespaceOnPasteMode:
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
) as Array<PortableTextBlock>
|
|
61
|
+
legacySchema.block.options.unstable_whitespaceOnPasteMode,
|
|
62
|
+
}) as Array<PortableTextBlock>
|
|
62
63
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
64
|
+
const parsedBlocks = blocks.flatMap((block) => {
|
|
65
|
+
const parsedBlock = parseBlock({
|
|
66
|
+
context: snapshot.context,
|
|
67
|
+
block,
|
|
68
|
+
options: {
|
|
69
|
+
refreshKeys: false,
|
|
70
|
+
},
|
|
71
|
+
})
|
|
72
|
+
return parsedBlock ? [parsedBlock] : []
|
|
70
73
|
})
|
|
71
|
-
return parsedBlock ? [parsedBlock] : []
|
|
72
|
-
})
|
|
73
74
|
|
|
74
|
-
|
|
75
|
+
if (parsedBlocks.length === 0) {
|
|
76
|
+
return {
|
|
77
|
+
type: 'deserialization.failure',
|
|
78
|
+
mimeType: 'text/html',
|
|
79
|
+
reason: 'No blocks deserialized',
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
75
83
|
return {
|
|
76
|
-
type: 'deserialization.
|
|
84
|
+
type: 'deserialization.success',
|
|
85
|
+
data: parsedBlocks,
|
|
77
86
|
mimeType: 'text/html',
|
|
78
|
-
reason: 'No blocks deserialized',
|
|
79
87
|
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
type: 'deserialization.success',
|
|
84
|
-
data: parsedBlocks,
|
|
85
|
-
mimeType: 'text/html',
|
|
86
|
-
}
|
|
87
|
-
},
|
|
88
|
-
})
|
|
88
|
+
},
|
|
89
|
+
})
|
|
90
|
+
}
|
|
@@ -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
|
@@ -232,12 +232,12 @@ export const PortableTextEditable = forwardRef<
|
|
|
232
232
|
renderChild={renderChild}
|
|
233
233
|
renderListItem={renderListItem}
|
|
234
234
|
renderStyle={renderStyle}
|
|
235
|
-
schemaTypes={schemaTypes}
|
|
235
|
+
schemaTypes={portableTextEditor.schemaTypes}
|
|
236
236
|
spellCheck={spellCheck}
|
|
237
237
|
/>
|
|
238
238
|
),
|
|
239
239
|
[
|
|
240
|
-
|
|
240
|
+
portableTextEditor,
|
|
241
241
|
spellCheck,
|
|
242
242
|
readOnly,
|
|
243
243
|
renderBlock,
|
|
@@ -258,7 +258,7 @@ export const PortableTextEditable = forwardRef<
|
|
|
258
258
|
<Leaf
|
|
259
259
|
{...lProps}
|
|
260
260
|
editorActor={editorActor}
|
|
261
|
-
schemaTypes={schemaTypes}
|
|
261
|
+
schemaTypes={portableTextEditor.schemaTypes}
|
|
262
262
|
renderAnnotation={renderAnnotation}
|
|
263
263
|
renderChild={renderChild}
|
|
264
264
|
renderDecorator={renderDecorator}
|
|
@@ -289,12 +289,12 @@ export const PortableTextEditable = forwardRef<
|
|
|
289
289
|
},
|
|
290
290
|
[
|
|
291
291
|
editorActor,
|
|
292
|
+
portableTextEditor.schemaTypes,
|
|
292
293
|
readOnly,
|
|
293
294
|
renderAnnotation,
|
|
294
295
|
renderChild,
|
|
295
296
|
renderDecorator,
|
|
296
297
|
renderPlaceholder,
|
|
297
|
-
schemaTypes,
|
|
298
298
|
],
|
|
299
299
|
)
|
|
300
300
|
|
|
@@ -453,7 +453,12 @@ export const PortableTextEditable = forwardRef<
|
|
|
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()
|