@portabletext/editor 3.1.2 → 3.2.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/README.md +7 -0
- package/lib/_chunks-es/util.slice-blocks.js.map +1 -1
- package/lib/behaviors/index.js.map +1 -1
- package/lib/index.js +75 -1
- package/lib/index.js.map +1 -1
- package/package.json +3 -2
- package/src/behaviors/behavior.abstract.deserialize.ts +26 -0
- package/src/behaviors/behavior.abstract.serialize.ts +5 -0
- package/src/behaviors/behavior.types.behavior.ts +4 -6
- package/src/behaviors/behavior.types.event.ts +2 -4
- package/src/converters/converter.text-markdown.ts +67 -0
- package/src/converters/converters.core.ts +2 -0
- package/src/types/slate.ts +4 -2
- package/src/utils/util.get-selection-end-point.ts +4 -4
- package/src/utils/util.get-selection-start-point.ts +4 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@portabletext/editor",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": "Portable Text Editor made in React",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -75,12 +75,13 @@
|
|
|
75
75
|
"xstate": "^5.24.0",
|
|
76
76
|
"@portabletext/block-tools": "^4.1.4",
|
|
77
77
|
"@portabletext/keyboard-shortcuts": "^2.1.0",
|
|
78
|
+
"@portabletext/markdown": "^1.0.1",
|
|
78
79
|
"@portabletext/patches": "^2.0.0",
|
|
79
80
|
"@portabletext/schema": "^2.0.0"
|
|
80
81
|
},
|
|
81
82
|
"devDependencies": {
|
|
82
83
|
"@sanity/diff-match-patch": "^3.2.0",
|
|
83
|
-
"@sanity/pkg-utils": "^
|
|
84
|
+
"@sanity/pkg-utils": "^10.0.0",
|
|
84
85
|
"@sanity/schema": "^4.20.0",
|
|
85
86
|
"@sanity/types": "^4.20.0",
|
|
86
87
|
"@types/debug": "^4.1.12",
|
|
@@ -35,6 +35,18 @@ export const abstractDeserializeBehaviors = [
|
|
|
35
35
|
} as const
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
const markdown =
|
|
39
|
+
event.originEvent.originEvent.dataTransfer.getData('text/markdown')
|
|
40
|
+
|
|
41
|
+
if (markdown) {
|
|
42
|
+
return {
|
|
43
|
+
type: 'deserialize.data',
|
|
44
|
+
mimeType: 'text/markdown',
|
|
45
|
+
data: markdown,
|
|
46
|
+
originEvent: event.originEvent,
|
|
47
|
+
} as const
|
|
48
|
+
}
|
|
49
|
+
|
|
38
50
|
const html =
|
|
39
51
|
event.originEvent.originEvent.dataTransfer.getData('text/html')
|
|
40
52
|
|
|
@@ -199,6 +211,20 @@ export const abstractDeserializeBehaviors = [
|
|
|
199
211
|
}
|
|
200
212
|
|
|
201
213
|
if (event.mimeType === 'application/json') {
|
|
214
|
+
const markdown =
|
|
215
|
+
event.originEvent.originEvent.dataTransfer.getData('text/markdown')
|
|
216
|
+
|
|
217
|
+
if (markdown) {
|
|
218
|
+
return {
|
|
219
|
+
type: 'deserialize.data',
|
|
220
|
+
mimeType: 'text/markdown',
|
|
221
|
+
data: markdown,
|
|
222
|
+
originEvent: event.originEvent,
|
|
223
|
+
} as const
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (event.mimeType === 'text/markdown') {
|
|
202
228
|
const html =
|
|
203
229
|
event.originEvent.originEvent.dataTransfer.getData('text/html')
|
|
204
230
|
|
|
@@ -16,6 +16,11 @@ export const abstractSerializeBehaviors = [
|
|
|
16
16
|
mimeType: 'application/json',
|
|
17
17
|
originEvent: event.originEvent,
|
|
18
18
|
}),
|
|
19
|
+
raise({
|
|
20
|
+
type: 'serialize.data',
|
|
21
|
+
mimeType: 'text/markdown',
|
|
22
|
+
originEvent: event.originEvent,
|
|
23
|
+
}),
|
|
19
24
|
raise({
|
|
20
25
|
type: 'serialize.data',
|
|
21
26
|
mimeType: 'text/html',
|
|
@@ -19,8 +19,8 @@ export type Behavior<
|
|
|
19
19
|
| `${BehaviorEventTypeNamespace}.*`
|
|
20
20
|
| BehaviorEvent['type'],
|
|
21
21
|
TGuardResponse = true,
|
|
22
|
-
TBehaviorEvent extends
|
|
23
|
-
ResolveBehaviorEvent<TBehaviorEventType
|
|
22
|
+
TBehaviorEvent extends ResolveBehaviorEvent<TBehaviorEventType> =
|
|
23
|
+
ResolveBehaviorEvent<TBehaviorEventType>,
|
|
24
24
|
> = {
|
|
25
25
|
/**
|
|
26
26
|
* Editor Event that triggers this Behavior.
|
|
@@ -74,10 +74,8 @@ export function defineBehavior<
|
|
|
74
74
|
| `${BehaviorEventTypeNamespace}.*`
|
|
75
75
|
| BehaviorEvent['type'] = BehaviorEvent['type'],
|
|
76
76
|
TGuardResponse = true,
|
|
77
|
-
TBehaviorEvent extends ResolveBehaviorEvent<
|
|
78
|
-
TBehaviorEventType,
|
|
79
|
-
TPayload
|
|
80
|
-
> = ResolveBehaviorEvent<TBehaviorEventType, TPayload>,
|
|
77
|
+
TBehaviorEvent extends ResolveBehaviorEvent<TBehaviorEventType, TPayload> =
|
|
78
|
+
ResolveBehaviorEvent<TBehaviorEventType, TPayload>,
|
|
81
79
|
>(
|
|
82
80
|
behavior: Behavior<TBehaviorEventType, TGuardResponse, TBehaviorEvent>,
|
|
83
81
|
): Behavior {
|
|
@@ -625,10 +625,8 @@ type CustomBehaviorEventType<
|
|
|
625
625
|
export type CustomBehaviorEvent<
|
|
626
626
|
TPayload extends Record<string, unknown> = Record<string, unknown>,
|
|
627
627
|
TType extends string = string,
|
|
628
|
-
TInternalType extends CustomBehaviorEventType<
|
|
629
|
-
'custom',
|
|
630
|
-
TType
|
|
631
|
-
> = CustomBehaviorEventType<'custom', TType>,
|
|
628
|
+
TInternalType extends CustomBehaviorEventType<'custom', TType> =
|
|
629
|
+
CustomBehaviorEventType<'custom', TType>,
|
|
632
630
|
> = {
|
|
633
631
|
type: TInternalType
|
|
634
632
|
} & TPayload
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import {
|
|
2
|
+
markdownToPortableText,
|
|
3
|
+
portableTextToMarkdown,
|
|
4
|
+
} from '@portabletext/markdown'
|
|
5
|
+
import {getSelectedValue} from '../selectors/selector.get-selected-value'
|
|
6
|
+
import {parseBlock} from '../utils/parse-blocks'
|
|
7
|
+
import {defineConverter} from './converter.types'
|
|
8
|
+
|
|
9
|
+
export const converterTextMarkdown = defineConverter({
|
|
10
|
+
mimeType: 'text/markdown',
|
|
11
|
+
serialize: ({snapshot, event}) => {
|
|
12
|
+
const selection = snapshot.context.selection
|
|
13
|
+
|
|
14
|
+
if (!selection) {
|
|
15
|
+
return {
|
|
16
|
+
type: 'serialization.failure',
|
|
17
|
+
mimeType: 'text/markdown',
|
|
18
|
+
reason: 'No selection',
|
|
19
|
+
originEvent: event.originEvent,
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const blocks = getSelectedValue(snapshot)
|
|
24
|
+
|
|
25
|
+
const markdown = portableTextToMarkdown(blocks)
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
type: 'serialization.success',
|
|
29
|
+
data: markdown,
|
|
30
|
+
mimeType: 'text/markdown',
|
|
31
|
+
originEvent: event.originEvent,
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
deserialize: ({snapshot, event}) => {
|
|
35
|
+
const blocks = markdownToPortableText(event.data, {
|
|
36
|
+
keyGenerator: snapshot.context.keyGenerator,
|
|
37
|
+
schema: snapshot.context.schema,
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
const parsedBlocks = blocks.flatMap((block) => {
|
|
41
|
+
const parsedBlock = parseBlock({
|
|
42
|
+
context: snapshot.context,
|
|
43
|
+
block,
|
|
44
|
+
options: {
|
|
45
|
+
normalize: false,
|
|
46
|
+
removeUnusedMarkDefs: true,
|
|
47
|
+
validateFields: false,
|
|
48
|
+
},
|
|
49
|
+
})
|
|
50
|
+
return parsedBlock ? [parsedBlock] : []
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
if (parsedBlocks.length === 0) {
|
|
54
|
+
return {
|
|
55
|
+
type: 'deserialization.failure',
|
|
56
|
+
mimeType: 'text/markdown',
|
|
57
|
+
reason: 'No blocks deserialized',
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
type: 'deserialization.success',
|
|
63
|
+
data: parsedBlocks,
|
|
64
|
+
mimeType: 'text/markdown',
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
})
|
|
@@ -2,6 +2,7 @@ import type {PortableTextMemberSchemaTypes} from '../types/editor'
|
|
|
2
2
|
import {converterJson} from './converter.json'
|
|
3
3
|
import {converterPortableText} from './converter.portable-text'
|
|
4
4
|
import {createConverterTextHtml} from './converter.text-html'
|
|
5
|
+
import {converterTextMarkdown} from './converter.text-markdown'
|
|
5
6
|
import {createConverterTextPlain} from './converter.text-plain'
|
|
6
7
|
|
|
7
8
|
export function createCoreConverters(
|
|
@@ -10,6 +11,7 @@ export function createCoreConverters(
|
|
|
10
11
|
return [
|
|
11
12
|
converterJson,
|
|
12
13
|
converterPortableText,
|
|
14
|
+
converterTextMarkdown,
|
|
13
15
|
createConverterTextHtml(legacySchema),
|
|
14
16
|
createConverterTextPlain(legacySchema),
|
|
15
17
|
]
|
package/src/types/slate.ts
CHANGED
|
@@ -11,8 +11,10 @@ export interface VoidElement {
|
|
|
11
11
|
value: Record<string, unknown>
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
export interface SlateTextBlock
|
|
15
|
-
|
|
14
|
+
export interface SlateTextBlock extends Omit<
|
|
15
|
+
PortableTextTextBlock,
|
|
16
|
+
'children'
|
|
17
|
+
> {
|
|
16
18
|
children: Descendant[]
|
|
17
19
|
}
|
|
18
20
|
|
|
@@ -5,10 +5,10 @@ import type {EditorSelection, EditorSelectionPoint} from '../types/editor'
|
|
|
5
5
|
*/
|
|
6
6
|
export function getSelectionEndPoint<
|
|
7
7
|
TEditorSelection extends NonNullable<EditorSelection> | null,
|
|
8
|
-
TEditorSelectionPoint extends
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
TEditorSelectionPoint extends EditorSelectionPoint | null =
|
|
9
|
+
TEditorSelection extends NonNullable<EditorSelection>
|
|
10
|
+
? EditorSelectionPoint
|
|
11
|
+
: null,
|
|
12
12
|
>(selection: TEditorSelection): TEditorSelectionPoint {
|
|
13
13
|
if (!selection) {
|
|
14
14
|
return null as TEditorSelectionPoint
|
|
@@ -5,10 +5,10 @@ import type {EditorSelection, EditorSelectionPoint} from '../types/editor'
|
|
|
5
5
|
*/
|
|
6
6
|
export function getSelectionStartPoint<
|
|
7
7
|
TEditorSelection extends NonNullable<EditorSelection> | null,
|
|
8
|
-
TEditorSelectionPoint extends
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
TEditorSelectionPoint extends EditorSelectionPoint | null =
|
|
9
|
+
TEditorSelection extends NonNullable<EditorSelection>
|
|
10
|
+
? EditorSelectionPoint
|
|
11
|
+
: null,
|
|
12
12
|
>(selection: TEditorSelection): TEditorSelectionPoint {
|
|
13
13
|
if (!selection) {
|
|
14
14
|
return null as TEditorSelectionPoint
|