@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
package/lib/utils/index.d.ts
CHANGED
|
@@ -1,21 +1,16 @@
|
|
|
1
1
|
import type {Patch} from '@portabletext/patches'
|
|
2
|
-
import type {
|
|
3
|
-
ArraySchemaType,
|
|
4
|
-
BlockDecoratorDefinition,
|
|
5
|
-
BlockListDefinition,
|
|
6
|
-
BlockStyleDefinition,
|
|
7
|
-
ObjectSchemaType,
|
|
8
|
-
Path,
|
|
9
|
-
PortableTextChild,
|
|
10
|
-
PortableTextListBlock,
|
|
11
|
-
PortableTextTextBlock,
|
|
12
|
-
} from '@sanity/types'
|
|
13
2
|
import {
|
|
14
3
|
KeyedSegment,
|
|
15
4
|
PortableTextBlock,
|
|
16
5
|
PortableTextObject,
|
|
17
6
|
PortableTextSpan,
|
|
18
7
|
} from '@sanity/types'
|
|
8
|
+
import type {
|
|
9
|
+
Path,
|
|
10
|
+
PortableTextChild,
|
|
11
|
+
PortableTextListBlock,
|
|
12
|
+
PortableTextTextBlock,
|
|
13
|
+
} from '@sanity/types'
|
|
19
14
|
import type {
|
|
20
15
|
FocusEvent as FocusEvent_2,
|
|
21
16
|
KeyboardEvent as KeyboardEvent_2,
|
|
@@ -44,7 +39,6 @@ import {
|
|
|
44
39
|
Values,
|
|
45
40
|
} from 'xstate'
|
|
46
41
|
import {GuardArgs} from 'xstate/guards'
|
|
47
|
-
import {PortableTextMemberSchemaTypes as PortableTextMemberSchemaTypes_2} from '..'
|
|
48
42
|
|
|
49
43
|
declare type AbstractBehaviorEvent =
|
|
50
44
|
| {
|
|
@@ -219,6 +213,14 @@ declare const abstractBehaviorEventTypes: readonly [
|
|
|
219
213
|
'style.toggle',
|
|
220
214
|
]
|
|
221
215
|
|
|
216
|
+
/**
|
|
217
|
+
* @public
|
|
218
|
+
*/
|
|
219
|
+
declare type BaseDefinition = {
|
|
220
|
+
name: string
|
|
221
|
+
title?: string
|
|
222
|
+
}
|
|
223
|
+
|
|
222
224
|
/**
|
|
223
225
|
* @beta
|
|
224
226
|
*/
|
|
@@ -1222,7 +1224,7 @@ declare const editorMachine: StateMachine<
|
|
|
1222
1224
|
converters: Set<Converter>
|
|
1223
1225
|
keyGenerator: () => string
|
|
1224
1226
|
pendingEvents: never[]
|
|
1225
|
-
schema:
|
|
1227
|
+
schema: EditorSchema
|
|
1226
1228
|
selection: null
|
|
1227
1229
|
initialReadOnly: boolean
|
|
1228
1230
|
maxBlocks: number | undefined
|
|
@@ -4702,7 +4704,65 @@ declare const editorMachine: StateMachine<
|
|
|
4702
4704
|
/**
|
|
4703
4705
|
* @public
|
|
4704
4706
|
*/
|
|
4705
|
-
declare type EditorSchema =
|
|
4707
|
+
declare type EditorSchema = {
|
|
4708
|
+
annotations: ReadonlyArray<
|
|
4709
|
+
BaseDefinition & {
|
|
4710
|
+
fields: ReadonlyArray<{
|
|
4711
|
+
name: string
|
|
4712
|
+
type: string
|
|
4713
|
+
}>
|
|
4714
|
+
}
|
|
4715
|
+
>
|
|
4716
|
+
block: {
|
|
4717
|
+
name: string
|
|
4718
|
+
}
|
|
4719
|
+
blockObjects: ReadonlyArray<
|
|
4720
|
+
BaseDefinition & {
|
|
4721
|
+
fields: ReadonlyArray<{
|
|
4722
|
+
name: string
|
|
4723
|
+
type: string
|
|
4724
|
+
}>
|
|
4725
|
+
}
|
|
4726
|
+
>
|
|
4727
|
+
decorators: ReadonlyArray<
|
|
4728
|
+
BaseDefinition & {
|
|
4729
|
+
/**
|
|
4730
|
+
* @deprecated
|
|
4731
|
+
* Use `name` instead
|
|
4732
|
+
*/
|
|
4733
|
+
value: string
|
|
4734
|
+
}
|
|
4735
|
+
>
|
|
4736
|
+
inlineObjects: ReadonlyArray<
|
|
4737
|
+
BaseDefinition & {
|
|
4738
|
+
fields: ReadonlyArray<{
|
|
4739
|
+
name: string
|
|
4740
|
+
type: string
|
|
4741
|
+
}>
|
|
4742
|
+
}
|
|
4743
|
+
>
|
|
4744
|
+
span: {
|
|
4745
|
+
name: string
|
|
4746
|
+
}
|
|
4747
|
+
styles: ReadonlyArray<
|
|
4748
|
+
BaseDefinition & {
|
|
4749
|
+
/**
|
|
4750
|
+
* @deprecated
|
|
4751
|
+
* Use `name` instead
|
|
4752
|
+
*/
|
|
4753
|
+
value: string
|
|
4754
|
+
}
|
|
4755
|
+
>
|
|
4756
|
+
lists: ReadonlyArray<
|
|
4757
|
+
BaseDefinition & {
|
|
4758
|
+
/**
|
|
4759
|
+
* @deprecated
|
|
4760
|
+
* Use `name` instead
|
|
4761
|
+
*/
|
|
4762
|
+
value: string
|
|
4763
|
+
}
|
|
4764
|
+
>
|
|
4765
|
+
}
|
|
4706
4766
|
|
|
4707
4767
|
/** @public */
|
|
4708
4768
|
declare type EditorSelection = {
|
|
@@ -5038,21 +5098,6 @@ declare type PickFromUnion<
|
|
|
5038
5098
|
TPickedTags extends TUnion[TTagKey],
|
|
5039
5099
|
> = TUnion extends Record<TTagKey, TPickedTags> ? TUnion : never
|
|
5040
5100
|
|
|
5041
|
-
/** @beta */
|
|
5042
|
-
declare type PortableTextMemberSchemaTypes = {
|
|
5043
|
-
annotations: (ObjectSchemaType & {
|
|
5044
|
-
i18nTitleKey?: string
|
|
5045
|
-
})[]
|
|
5046
|
-
block: ObjectSchemaType
|
|
5047
|
-
blockObjects: ObjectSchemaType[]
|
|
5048
|
-
decorators: BlockDecoratorDefinition[]
|
|
5049
|
-
inlineObjects: ObjectSchemaType[]
|
|
5050
|
-
portableText: ArraySchemaType<PortableTextBlock>
|
|
5051
|
-
span: ObjectSchemaType
|
|
5052
|
-
styles: BlockStyleDefinition[]
|
|
5053
|
-
lists: BlockListDefinition[]
|
|
5054
|
-
}
|
|
5055
|
-
|
|
5056
5101
|
declare interface PortableTextSlateEditor extends ReactEditor {
|
|
5057
5102
|
_key: 'editor'
|
|
5058
5103
|
_type: 'editor'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@portabletext/editor",
|
|
3
|
-
"version": "1.47.
|
|
3
|
+
"version": "1.47.2",
|
|
4
4
|
"description": "Portable Text Editor made in React",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -80,14 +80,14 @@
|
|
|
80
80
|
"use-effect-event": "^1.0.2",
|
|
81
81
|
"xstate": "^5.19.2",
|
|
82
82
|
"@portabletext/patches": "1.1.3",
|
|
83
|
-
"@portabletext/block-tools": "1.1.
|
|
83
|
+
"@portabletext/block-tools": "1.1.18"
|
|
84
84
|
},
|
|
85
85
|
"devDependencies": {
|
|
86
86
|
"@portabletext/toolkit": "^2.0.17",
|
|
87
87
|
"@sanity/diff-match-patch": "^3.2.0",
|
|
88
88
|
"@sanity/pkg-utils": "^7.2.2",
|
|
89
|
-
"@sanity/schema": "^3.
|
|
90
|
-
"@sanity/types": "^3.
|
|
89
|
+
"@sanity/schema": "^3.84.0",
|
|
90
|
+
"@sanity/types": "^3.84.0",
|
|
91
91
|
"@testing-library/jest-dom": "^6.6.3",
|
|
92
92
|
"@testing-library/react": "^16.3.0",
|
|
93
93
|
"@types/debug": "^4.1.12",
|
|
@@ -115,8 +115,8 @@
|
|
|
115
115
|
"racejar": "1.2.3"
|
|
116
116
|
},
|
|
117
117
|
"peerDependencies": {
|
|
118
|
-
"@sanity/schema": "^3.
|
|
119
|
-
"@sanity/types": "^3.
|
|
118
|
+
"@sanity/schema": "^3.84.0",
|
|
119
|
+
"@sanity/types": "^3.84.0",
|
|
120
120
|
"react": "^16.9 || ^17 || ^18 || ^19",
|
|
121
121
|
"rxjs": "^7.8.2"
|
|
122
122
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {Editor, Path, Point, Range, Transforms, type Descendant} from 'slate'
|
|
2
2
|
import {DOMEditor} from 'slate-dom'
|
|
3
|
-
import type {EditorSchema} from '../editor/
|
|
3
|
+
import type {EditorSchema} from '../editor/editor-schema'
|
|
4
4
|
import {parseBlock} from '../internal-utils/parse-blocks'
|
|
5
5
|
import {
|
|
6
6
|
getFocusBlock,
|
|
@@ -88,7 +88,7 @@ export const splitBlockActionImplementation: BehaviorActionImplementation<
|
|
|
88
88
|
// previous block
|
|
89
89
|
for (const mark of marks) {
|
|
90
90
|
if (
|
|
91
|
-
schema.decorators.some((decorator) => decorator.
|
|
91
|
+
schema.decorators.some((decorator) => decorator.name === mark)
|
|
92
92
|
) {
|
|
93
93
|
continue
|
|
94
94
|
}
|
|
@@ -8,7 +8,7 @@ export const coreDecoratorBehaviors = {
|
|
|
8
8
|
guard: ({snapshot, event}) =>
|
|
9
9
|
isHotkey('mod+b', event.originEvent) &&
|
|
10
10
|
snapshot.context.schema.decorators.some(
|
|
11
|
-
(decorator) => decorator.
|
|
11
|
+
(decorator) => decorator.name === 'strong',
|
|
12
12
|
),
|
|
13
13
|
actions: [() => [raise({type: 'decorator.toggle', decorator: 'strong'})]],
|
|
14
14
|
}),
|
|
@@ -17,7 +17,7 @@ export const coreDecoratorBehaviors = {
|
|
|
17
17
|
guard: ({snapshot, event}) =>
|
|
18
18
|
isHotkey('mod+i', event.originEvent) &&
|
|
19
19
|
snapshot.context.schema.decorators.some(
|
|
20
|
-
(decorator) => decorator.
|
|
20
|
+
(decorator) => decorator.name === 'em',
|
|
21
21
|
),
|
|
22
22
|
actions: [() => [raise({type: 'decorator.toggle', decorator: 'em'})]],
|
|
23
23
|
}),
|
|
@@ -26,7 +26,7 @@ export const coreDecoratorBehaviors = {
|
|
|
26
26
|
guard: ({snapshot, event}) =>
|
|
27
27
|
isHotkey('mod+u', event.originEvent) &&
|
|
28
28
|
snapshot.context.schema.decorators.some(
|
|
29
|
-
(decorator) => decorator.
|
|
29
|
+
(decorator) => decorator.name === 'underline',
|
|
30
30
|
),
|
|
31
31
|
actions: [
|
|
32
32
|
() => [raise({type: 'decorator.toggle', decorator: 'underline'})],
|
|
@@ -37,7 +37,7 @@ export const coreDecoratorBehaviors = {
|
|
|
37
37
|
guard: ({snapshot, event}) =>
|
|
38
38
|
isHotkey("mod+'", event.originEvent) &&
|
|
39
39
|
snapshot.context.schema.decorators.some(
|
|
40
|
-
(decorator) => decorator.
|
|
40
|
+
(decorator) => decorator.name === 'code',
|
|
41
41
|
),
|
|
42
42
|
actions: [() => [raise({type: 'decorator.toggle', decorator: 'code'})]],
|
|
43
43
|
}),
|
|
@@ -40,7 +40,7 @@ const breakingAtTheEndOfTextBlock = defineBehavior({
|
|
|
40
40
|
markDefs: [],
|
|
41
41
|
listItem: focusListItem,
|
|
42
42
|
level: focusLevel,
|
|
43
|
-
style: snapshot.context.schema.styles[0]?.
|
|
43
|
+
style: snapshot.context.schema.styles[0]?.name,
|
|
44
44
|
},
|
|
45
45
|
placement: 'after',
|
|
46
46
|
}),
|
|
@@ -63,14 +63,14 @@ const breakingAtTheStartOfTextBlock = defineBehavior({
|
|
|
63
63
|
const focusDecorators = focusSpan?.node.marks?.filter(
|
|
64
64
|
(mark) =>
|
|
65
65
|
snapshot.context.schema.decorators.some(
|
|
66
|
-
(decorator) => decorator.
|
|
66
|
+
(decorator) => decorator.name === mark,
|
|
67
67
|
) ?? [],
|
|
68
68
|
)
|
|
69
69
|
const focusAnnotations =
|
|
70
70
|
focusSpan?.node.marks?.filter(
|
|
71
71
|
(mark) =>
|
|
72
72
|
!snapshot.context.schema.decorators.some(
|
|
73
|
-
(decorator) => decorator.
|
|
73
|
+
(decorator) => decorator.name === mark,
|
|
74
74
|
),
|
|
75
75
|
) ?? []
|
|
76
76
|
const focusListItem = focusTextBlock.node.listItem
|
|
@@ -103,7 +103,7 @@ const breakingAtTheStartOfTextBlock = defineBehavior({
|
|
|
103
103
|
],
|
|
104
104
|
listItem: focusListItem,
|
|
105
105
|
level: focusLevel,
|
|
106
|
-
style: snapshot.context.schema.styles[0]?.
|
|
106
|
+
style: snapshot.context.schema.styles[0]?.name,
|
|
107
107
|
},
|
|
108
108
|
placement: 'before',
|
|
109
109
|
select: 'none',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {EditorSchema} from '../editor/
|
|
1
|
+
import type {EditorSchema} from '../editor/editor-schema'
|
|
2
2
|
import {createPairRegex} from '../internal-utils/get-text-to-emphasize'
|
|
3
3
|
import * as selectors from '../selectors'
|
|
4
4
|
import type {BlockOffset} from '../types/block-offset'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {EditorSchema} from '../editor/
|
|
1
|
+
import type {EditorSchema} from '../editor/editor-schema'
|
|
2
2
|
import {looksLikeUrl} from '../internal-utils/looks-like-url'
|
|
3
3
|
import * as selectors from '../selectors'
|
|
4
4
|
import {execute} from './behavior.types.action'
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {isPortableTextTextBlock} from '@sanity/types'
|
|
2
|
-
import type {EditorSchema} from '../editor/
|
|
2
|
+
import type {EditorSchema} from '../editor/editor-schema'
|
|
3
3
|
import * as selectors from '../selectors'
|
|
4
4
|
import {spanSelectionPointToBlockOffset} from '../utils/util.block-offset'
|
|
5
5
|
import {getTextBlockText} from '../utils/util.get-text-block-text'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type {Behavior, BehaviorEvent} from '.'
|
|
2
2
|
import {performAction} from '../behavior-actions/behavior.actions'
|
|
3
|
-
import type {EditorSchema} from '../editor/
|
|
3
|
+
import type {EditorSchema} from '../editor/editor-schema'
|
|
4
4
|
import type {EditorSnapshot} from '../editor/editor-snapshot'
|
|
5
5
|
import {
|
|
6
6
|
withApplyingBehaviorActions,
|
|
@@ -3,15 +3,14 @@ import {
|
|
|
3
3
|
compileSchemaDefinition,
|
|
4
4
|
defineSchema,
|
|
5
5
|
type SchemaDefinition,
|
|
6
|
-
} from '../editor/
|
|
6
|
+
} from '../editor/editor-schema'
|
|
7
7
|
import {createTestSnapshot} from '../internal-utils/create-test-snapshot'
|
|
8
8
|
import {converterPortableText} from './converter.portable-text'
|
|
9
|
-
import {coreConverters} from './converters.core'
|
|
10
9
|
|
|
11
10
|
function createSnapshot(schema: SchemaDefinition) {
|
|
12
11
|
return createTestSnapshot({
|
|
13
12
|
context: {
|
|
14
|
-
converters:
|
|
13
|
+
converters: [],
|
|
15
14
|
schema: compileSchemaDefinition(schema),
|
|
16
15
|
},
|
|
17
16
|
})
|
|
@@ -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
|
+
}
|