@portabletext/editor 3.0.6 → 3.0.7

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.
@@ -145,7 +145,7 @@ function insertPatch(
145
145
  const normalizedIdx =
146
146
  position === 'after' ? targetBlockIndex + 1 : targetBlockIndex
147
147
 
148
- const editorWasEmptyBefore = isEqualToEmptyEditor(editor.children, schema)
148
+ const editorWasEmptyBefore = isEqualToEmptyEditor(editor.value, schema)
149
149
 
150
150
  Transforms.insertNodes(editor, blocksToInsert, {at: [normalizedIdx]})
151
151
 
@@ -1,5 +1,9 @@
1
1
  import {compileSchemaDefinitionToPortableTextMemberSchemaTypes} from '@portabletext/sanity-bridge'
2
- import {compileSchema, defineSchema} from '@portabletext/schema'
2
+ import {
3
+ compileSchema,
4
+ defineSchema,
5
+ type PortableTextBlock,
6
+ } from '@portabletext/schema'
3
7
  import type {PortableTextTextBlock} from '@sanity/types'
4
8
  import {createEditor, type Descendant} from 'slate'
5
9
  import {beforeEach, describe, expect, it, test} from 'vitest'
@@ -32,13 +36,15 @@ const editorActor = createActor(editorMachine, {
32
36
  })
33
37
  const relayActor = createActor(relayMachine)
34
38
 
35
- const editor = withPlugins(createEditor(), {
39
+ const e = createEditor()
40
+ e.value = []
41
+ const editor = withPlugins(e, {
36
42
  editorActor,
37
43
  relayActor,
38
44
  subscriptions: [],
39
45
  })
40
46
 
41
- const createDefaultValue = () =>
47
+ const createDefaultChildren = () =>
42
48
  [
43
49
  {
44
50
  _type: 'block',
@@ -57,7 +63,25 @@ const createDefaultValue = () =>
57
63
  {_type: 'span', _key: 'fd9b4a4e6c0b', text: '', marks: []},
58
64
  ],
59
65
  },
60
- ] as Descendant[]
66
+ ] satisfies Array<Descendant>
67
+ const createDefaultValue = () =>
68
+ [
69
+ {
70
+ _type: 'block',
71
+ _key: '1f2e64b47787',
72
+ style: 'normal',
73
+ markDefs: [],
74
+ children: [
75
+ {_type: 'span', _key: 'c130395c640c', text: '', marks: []},
76
+ {
77
+ _key: '773866318fa8',
78
+ _type: 'someObject',
79
+ value: {title: 'The Object'},
80
+ },
81
+ {_type: 'span', _key: 'fd9b4a4e6c0b', text: '', marks: []},
82
+ ],
83
+ },
84
+ ] as Array<PortableTextBlock>
61
85
 
62
86
  describe(insertNodePatch.name, () => {
63
87
  test('Scenario: Inserting block object on empty editor', () => {
@@ -121,7 +145,7 @@ describe(insertNodePatch.name, () => {
121
145
 
122
146
  describe('operationToPatches', () => {
123
147
  beforeEach(() => {
124
- editor.children = createDefaultValue()
148
+ editor.children = createDefaultChildren()
125
149
  editor.onChange()
126
150
  })
127
151
 
@@ -418,12 +442,13 @@ describe('operationToPatches', () => {
418
442
  })
419
443
 
420
444
  it('produce correct remove block patch', () => {
445
+ const children = createDefaultChildren()
421
446
  const val = createDefaultValue()
422
447
  expect(
423
448
  removeNodePatch(editorActor.getSnapshot().context.schema, val, {
424
449
  type: 'remove_node',
425
450
  path: [0],
426
- node: val[0],
451
+ node: children[0],
427
452
  }),
428
453
  ).toMatchInlineSnapshot(`
429
454
  [
@@ -7,7 +7,7 @@ import {
7
7
  type InsertPosition,
8
8
  type Patch,
9
9
  } from '@portabletext/patches'
10
- import {isSpan, isTextBlock} from '@portabletext/schema'
10
+ import {isSpan, isTextBlock, type PortableTextBlock} from '@portabletext/schema'
11
11
  import type {Path, PortableTextSpan, PortableTextTextBlock} from '@sanity/types'
12
12
  import {
13
13
  Element,
@@ -29,7 +29,7 @@ export function insertTextPatch(
29
29
  schema: EditorSchema,
30
30
  children: Descendant[],
31
31
  operation: InsertTextOperation,
32
- beforeValue: Descendant[],
32
+ beforeValue: Array<PortableTextBlock>,
33
33
  ): Array<Patch> {
34
34
  const block =
35
35
  isTextBlock({schema}, children[operation.path[0]]) &&
@@ -62,7 +62,7 @@ export function removeTextPatch(
62
62
  schema: EditorSchema,
63
63
  children: Descendant[],
64
64
  operation: RemoveTextOperation,
65
- beforeValue: Descendant[],
65
+ beforeValue: Array<PortableTextBlock>,
66
66
  ): Array<Patch> {
67
67
  const block = children[operation.path[0]]
68
68
  if (!block) {
@@ -271,7 +271,7 @@ export function insertNodePatch(
271
271
  schema: EditorSchema,
272
272
  children: Descendant[],
273
273
  operation: InsertNodeOperation,
274
- beforeValue: Descendant[],
274
+ beforeValue: Array<PortableTextBlock>,
275
275
  ): Array<Patch> {
276
276
  const block = beforeValue[operation.path[0]]
277
277
  if (operation.path.length === 1) {
@@ -346,7 +346,7 @@ export function splitNodePatch(
346
346
  schema: EditorSchema,
347
347
  children: Descendant[],
348
348
  operation: SplitNodeOperation,
349
- beforeValue: Descendant[],
349
+ beforeValue: Array<PortableTextBlock>,
350
350
  ): Array<Patch> {
351
351
  const patches: Patch[] = []
352
352
  const splitBlock = children[operation.path[0]]
@@ -414,7 +414,7 @@ export function splitNodePatch(
414
414
 
415
415
  export function removeNodePatch(
416
416
  schema: EditorSchema,
417
- beforeValue: Descendant[],
417
+ beforeValue: Array<PortableTextBlock>,
418
418
  operation: RemoveNodeOperation,
419
419
  ): Array<Patch> {
420
420
  const block = beforeValue[operation.path[0]]
@@ -454,7 +454,7 @@ export function mergeNodePatch(
454
454
  schema: EditorSchema,
455
455
  children: Descendant[],
456
456
  operation: MergeNodeOperation,
457
- beforeValue: Descendant[],
457
+ beforeValue: Array<PortableTextBlock>,
458
458
  ): Array<Patch> {
459
459
  const patches: Patch[] = []
460
460
 
@@ -532,7 +532,7 @@ export function mergeNodePatch(
532
532
 
533
533
  export function moveNodePatch(
534
534
  schema: EditorSchema,
535
- beforeValue: Descendant[],
535
+ beforeValue: Array<PortableTextBlock>,
536
536
  operation: MoveNodeOperation,
537
537
  ): Array<Patch> {
538
538
  const patches: Patch[] = []
@@ -547,11 +547,7 @@ export function moveNodePatch(
547
547
  const position: InsertPosition =
548
548
  operation.path[0] > operation.newPath[0] ? 'before' : 'after'
549
549
  patches.push(unset([{_key: block._key}]))
550
- patches.push(
551
- insert([fromSlateBlock(block, schema.block.name)], position, [
552
- {_key: targetBlock._key},
553
- ]),
554
- )
550
+ patches.push(insert([block], position, [{_key: targetBlock._key}]))
555
551
  } else if (
556
552
  operation.path.length === 2 &&
557
553
  isTextBlock({schema}, block) &&
@@ -561,9 +557,7 @@ export function moveNodePatch(
561
557
  const targetChild = targetBlock.children[operation.newPath[1]]
562
558
  const position =
563
559
  operation.newPath[1] === targetBlock.children.length ? 'after' : 'before'
564
- const childToInsert = (
565
- fromSlateBlock(block, schema.block.name) as PortableTextTextBlock
566
- ).children[operation.path[1]]
560
+ const childToInsert = block.children[operation.path[1]]
567
561
  patches.push(unset([{_key: block._key}, 'children', {_key: child._key}]))
568
562
  patches.push(
569
563
  insert([childToInsert], position, [
@@ -125,14 +125,6 @@ export function toSlateBlock(
125
125
  ) as Descendant
126
126
  }
127
127
 
128
- export function fromSlateValue(
129
- value: Descendant[],
130
- textBlockType: string,
131
- keyMap: Record<string, PortableTextBlock | PortableTextChild> = {},
132
- ): PortableTextBlock[] {
133
- return value.map((block) => fromSlateBlock(block, textBlockType, keyMap))
134
- }
135
-
136
128
  export function fromSlateBlock(
137
129
  block: Descendant,
138
130
  textBlockType: string,
@@ -1,56 +1,32 @@
1
1
  import {isTextBlock} from '@portabletext/schema'
2
2
  import {omit} from 'lodash'
3
- import {Editor, Transforms} from 'slate'
4
- import {KEY_TO_VALUE_ELEMENT} from '../editor/weakMaps'
5
- import {toSlateRange} from '../internal-utils/to-slate-range'
6
- import {fromSlateBlock} from '../internal-utils/values'
3
+ import {Transforms} from 'slate'
7
4
  import {parseBlock} from '../utils/parse-blocks'
8
5
  import type {BehaviorOperationImplementation} from './behavior.operations'
9
6
 
10
7
  export const blockUnsetOperationImplementation: BehaviorOperationImplementation<
11
8
  'block.unset'
12
9
  > = ({context, operation}) => {
13
- const location = toSlateRange({
14
- context: {
15
- schema: context.schema,
16
- value: operation.editor.value,
17
- selection: {
18
- anchor: {path: operation.at, offset: 0},
19
- focus: {path: operation.at, offset: 0},
20
- },
21
- },
22
- blockIndexMap: operation.editor.blockIndexMap,
23
- })
10
+ const blockKey = operation.at[0]._key
11
+ const blockIndex = operation.editor.blockIndexMap.get(blockKey)
24
12
 
25
- if (!location) {
26
- throw new Error(
27
- `Unable to convert ${JSON.stringify(operation.at)} into a Slate Range`,
28
- )
13
+ if (blockIndex === undefined) {
14
+ throw new Error(`Unable to find block index for block key ${blockKey}`)
29
15
  }
30
16
 
31
- const blockEntry = Editor.node(operation.editor, location, {depth: 1})
32
- const block = blockEntry?.[0]
17
+ const block =
18
+ blockIndex !== undefined ? operation.editor.value.at(blockIndex) : undefined
33
19
 
34
20
  if (!block) {
35
21
  throw new Error(`Unable to find block at ${JSON.stringify(operation.at)}`)
36
22
  }
37
23
 
38
- const parsedBlock = fromSlateBlock(
39
- block,
40
- context.schema.block.name,
41
- KEY_TO_VALUE_ELEMENT.get(operation.editor),
42
- )
43
-
44
- if (!parsedBlock) {
45
- throw new Error(`Unable to parse block at ${JSON.stringify(operation.at)}`)
46
- }
47
-
48
- if (isTextBlock(context, parsedBlock)) {
24
+ if (isTextBlock(context, block)) {
49
25
  const propsToRemove = operation.props.filter((prop) => prop !== '_type')
50
26
 
51
27
  const updatedTextBlock = parseBlock({
52
28
  context,
53
- block: omit(parsedBlock, propsToRemove),
29
+ block: omit(block, propsToRemove),
54
30
  options: {
55
31
  normalize: false,
56
32
  removeUnusedMarkDefs: true,
@@ -74,7 +50,7 @@ export const blockUnsetOperationImplementation: BehaviorOperationImplementation<
74
50
  }
75
51
  }
76
52
 
77
- Transforms.setNodes(operation.editor, propsToSet, {at: location})
53
+ Transforms.setNodes(operation.editor, propsToSet, {at: [blockIndex]})
78
54
 
79
55
  return
80
56
  }
@@ -82,7 +58,7 @@ export const blockUnsetOperationImplementation: BehaviorOperationImplementation<
82
58
  const updatedBlockObject = parseBlock({
83
59
  context,
84
60
  block: omit(
85
- parsedBlock,
61
+ block,
86
62
  operation.props.filter((prop) => prop !== '_type'),
87
63
  ),
88
64
  options: {
@@ -105,6 +81,6 @@ export const blockUnsetOperationImplementation: BehaviorOperationImplementation<
105
81
  _key,
106
82
  value: props,
107
83
  },
108
- {at: location},
84
+ {at: [blockIndex]},
109
85
  )
110
86
  }
@@ -1,30 +1,48 @@
1
1
  import {applyAll} from '@portabletext/patches'
2
+ import {isTextBlock} from '@portabletext/schema'
2
3
  import {Editor, Element, Transforms} from 'slate'
3
- import {toSlateRange} from '../internal-utils/to-slate-range'
4
4
  import type {BehaviorOperationImplementation} from './behavior.operations'
5
5
 
6
6
  export const childUnsetOperationImplementation: BehaviorOperationImplementation<
7
7
  'child.unset'
8
8
  > = ({context, operation}) => {
9
- const location = toSlateRange({
10
- context: {
11
- schema: context.schema,
12
- value: operation.editor.value,
13
- selection: {
14
- anchor: {path: operation.at, offset: 0},
15
- focus: {path: operation.at, offset: 0},
16
- },
17
- },
18
- blockIndexMap: operation.editor.blockIndexMap,
19
- })
9
+ const blockKey = operation.at[0]._key
10
+ const blockIndex = operation.editor.blockIndexMap.get(blockKey)
11
+
12
+ if (blockIndex === undefined) {
13
+ throw new Error(`Unable to find block index for block key ${blockKey}`)
14
+ }
15
+
16
+ const block =
17
+ blockIndex !== undefined ? operation.editor.value.at(blockIndex) : undefined
18
+
19
+ if (!block) {
20
+ throw new Error(`Unable to find block at ${JSON.stringify(operation.at)}`)
21
+ }
22
+
23
+ if (!isTextBlock(context, block)) {
24
+ throw new Error(`Block ${JSON.stringify(blockKey)} is not a text block`)
25
+ }
26
+
27
+ const childKey = operation.at[2]._key
20
28
 
21
- if (!location) {
29
+ if (!childKey) {
22
30
  throw new Error(
23
- `Unable to convert ${JSON.stringify(operation.at)} into a Slate Range`,
31
+ `Unable to find child key at ${JSON.stringify(operation.at)}`,
24
32
  )
25
33
  }
26
34
 
27
- const childEntry = Editor.node(operation.editor, location, {depth: 2})
35
+ const childIndex = block.children.findIndex(
36
+ (child) => child._key === childKey,
37
+ )
38
+
39
+ if (childIndex === -1) {
40
+ throw new Error(`Unable to find child at ${JSON.stringify(operation.at)}`)
41
+ }
42
+
43
+ const childEntry = Editor.node(operation.editor, [blockIndex, childIndex], {
44
+ depth: 2,
45
+ })
28
46
  const child = childEntry?.[0]
29
47
  const childPath = childEntry?.[1]
30
48