@portabletext/editor 2.14.3 → 2.15.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.
@@ -1,14 +1,9 @@
1
1
  import type {Patch} from '@portabletext/patches'
2
+ import {isSpan} from '@portabletext/schema'
2
3
  import type {PortableTextBlock} from '@sanity/types'
3
4
  import {isEqual} from 'lodash'
4
- import {
5
- deleteText,
6
- Editor,
7
- Text,
8
- Transforms,
9
- type Descendant,
10
- type Node,
11
- } from 'slate'
5
+ import {deleteText, Editor, Transforms, type Descendant, type Node} from 'slate'
6
+ import type {ActorRefFrom} from 'xstate'
12
7
  import {
13
8
  and,
14
9
  assertEvent,
@@ -21,7 +16,6 @@ import {
21
16
  type AnyEventObject,
22
17
  type CallbackLogicFunction,
23
18
  } from 'xstate'
24
- import type {ActorRefFrom} from 'xstate'
25
19
  import {debugWithName} from '../internal-utils/debug'
26
20
  import {validateValue} from '../internal-utils/validateValue'
27
21
  import {toSlateBlock, VOID_CHILD_KEY} from '../internal-utils/values'
@@ -426,138 +420,102 @@ async function updateValue({
426
420
 
427
421
  const hadSelection = !!slateEditor.selection
428
422
 
429
- // If empty value, remove everything in the editor and insert a placeholder block
430
423
  if (!value || value.length === 0) {
431
424
  debug('Value is empty')
432
- Editor.withoutNormalizing(slateEditor, () => {
433
- withoutSaving(slateEditor, () => {
434
- withRemoteChanges(slateEditor, () => {
435
- withoutPatching(slateEditor, () => {
436
- if (doneSyncing) {
437
- return
438
- }
439
-
440
- if (hadSelection) {
441
- Transforms.deselect(slateEditor)
442
- }
443
-
444
- const childrenLength = slateEditor.children.length
445
425
 
446
- slateEditor.children.forEach((_, index) => {
447
- Transforms.removeNodes(slateEditor, {
448
- at: [childrenLength - 1 - index],
449
- })
450
- })
451
-
452
- Transforms.insertNodes(
453
- slateEditor,
454
- slateEditor.pteCreateTextBlock({decorators: []}),
455
- {at: [0]},
456
- )
457
-
458
- // Add a new selection in the top of the document
459
- if (hadSelection) {
460
- Transforms.select(slateEditor, [0, 0])
461
- }
462
- })
463
- })
464
- })
426
+ clearEditor({
427
+ slateEditor,
428
+ doneSyncing,
429
+ hadSelection,
465
430
  })
431
+
466
432
  isChanged = true
467
433
  }
434
+
468
435
  // Remove, replace or add nodes according to what is changed.
469
436
  if (value && value.length > 0) {
470
437
  if (streamBlocks) {
471
438
  await new Promise<void>((resolve) => {
472
- Editor.withoutNormalizing(slateEditor, () => {
473
- withRemoteChanges(slateEditor, () => {
474
- withoutPatching(slateEditor, () => {
475
- if (doneSyncing) {
476
- resolve()
477
- return
478
- }
479
-
480
- isChanged = removeExtraBlocks({
481
- slateEditor,
482
- value,
483
- })
439
+ if (doneSyncing) {
440
+ resolve()
441
+ return
442
+ }
484
443
 
485
- const processBlocks = async () => {
486
- for await (const [
487
- currentBlock,
488
- currentBlockIndex,
489
- ] of getStreamedBlocks({
490
- value,
491
- })) {
492
- const {blockChanged, blockValid} = syncBlock({
493
- context,
494
- sendBack,
495
- block: currentBlock,
496
- index: currentBlockIndex,
497
- slateEditor,
498
- value,
499
- })
500
-
501
- isChanged = blockChanged || isChanged
502
- isValid = isValid && blockValid
503
-
504
- if (!isValid) {
505
- break
506
- }
507
- }
508
-
509
- resolve()
510
- }
511
-
512
- processBlocks()
513
- })
514
- })
444
+ isChanged = removeExtraBlocks({
445
+ slateEditor,
446
+ value,
515
447
  })
516
- })
517
- } else {
518
- Editor.withoutNormalizing(slateEditor, () => {
519
- withRemoteChanges(slateEditor, () => {
520
- withoutPatching(slateEditor, () => {
521
- if (doneSyncing) {
522
- return
523
- }
524
448
 
525
- isChanged = removeExtraBlocks({
449
+ const processBlocks = async () => {
450
+ for await (const [
451
+ currentBlock,
452
+ currentBlockIndex,
453
+ ] of getStreamedBlocks({
454
+ value,
455
+ })) {
456
+ const {blockChanged, blockValid} = syncBlock({
457
+ context,
458
+ sendBack,
459
+ block: currentBlock,
460
+ index: currentBlockIndex,
526
461
  slateEditor,
527
462
  value,
528
463
  })
529
464
 
530
- let index = 0
465
+ isChanged = blockChanged || isChanged
466
+ isValid = isValid && blockValid
531
467
 
532
- for (const currentBlock of value) {
533
- const {blockChanged, blockValid} = syncBlock({
534
- context,
535
- sendBack,
536
- block: currentBlock,
537
- index,
538
- slateEditor,
539
- value,
540
- })
468
+ if (!isValid) {
469
+ break
470
+ }
471
+ }
541
472
 
542
- isChanged = blockChanged || isChanged
543
- isValid = isValid && blockValid
473
+ resolve()
474
+ }
544
475
 
545
- if (!blockValid) {
546
- break
547
- }
476
+ processBlocks()
477
+ })
478
+ } else {
479
+ if (doneSyncing) {
480
+ return
481
+ }
548
482
 
549
- index++
550
- }
551
- })
552
- })
483
+ isChanged = removeExtraBlocks({
484
+ slateEditor,
485
+ value,
553
486
  })
487
+
488
+ let index = 0
489
+
490
+ for (const block of value) {
491
+ const {blockChanged, blockValid} = syncBlock({
492
+ context,
493
+ sendBack,
494
+ block,
495
+ index,
496
+ slateEditor,
497
+ value,
498
+ })
499
+
500
+ isChanged = blockChanged || isChanged
501
+ isValid = isValid && blockValid
502
+
503
+ if (!blockValid) {
504
+ break
505
+ }
506
+
507
+ index++
508
+ }
554
509
  }
555
510
  }
556
511
 
557
512
  if (!isValid) {
558
513
  debug('Invalid value, returning')
514
+
559
515
  doneSyncing = true
516
+
560
517
  sendBack({type: 'done syncing', value})
518
+
561
519
  return
562
520
  }
563
521
 
@@ -567,31 +525,102 @@ async function updateValue({
567
525
  slateEditor.onChange()
568
526
  } catch (err) {
569
527
  console.error(err)
528
+
570
529
  sendBack({
571
530
  type: 'invalid value',
572
531
  resolution: null,
573
532
  value,
574
533
  })
534
+
575
535
  doneSyncing = true
536
+
576
537
  sendBack({type: 'done syncing', value})
538
+
577
539
  return
578
540
  }
541
+
579
542
  if (hadSelection && !slateEditor.selection) {
580
543
  Transforms.select(slateEditor, {
581
544
  anchor: {path: [0, 0], offset: 0},
582
545
  focus: {path: [0, 0], offset: 0},
583
546
  })
547
+
584
548
  slateEditor.onChange()
585
549
  }
550
+
586
551
  sendBack({type: 'value changed', value})
587
552
  } else {
588
553
  debug('Server value and editor value is equal, no need to sync.')
589
554
  }
590
555
 
591
556
  doneSyncing = true
557
+
592
558
  sendBack({type: 'done syncing', value})
593
559
  }
594
560
 
561
+ async function* getStreamedBlocks({value}: {value: Array<PortableTextBlock>}) {
562
+ let index = 0
563
+ for await (const block of value) {
564
+ if (index % 10 === 0) {
565
+ await new Promise<void>((resolve) => setTimeout(resolve, 0))
566
+ }
567
+ yield [block, index] as const
568
+ index++
569
+ }
570
+ }
571
+
572
+ /**
573
+ * Remove all blocks and insert a placeholder block
574
+ */
575
+ function clearEditor({
576
+ slateEditor,
577
+ doneSyncing,
578
+ hadSelection,
579
+ }: {
580
+ slateEditor: PortableTextSlateEditor
581
+ doneSyncing: boolean
582
+ hadSelection: boolean
583
+ }) {
584
+ Editor.withoutNormalizing(slateEditor, () => {
585
+ withoutSaving(slateEditor, () => {
586
+ withRemoteChanges(slateEditor, () => {
587
+ withoutPatching(slateEditor, () => {
588
+ if (doneSyncing) {
589
+ return
590
+ }
591
+
592
+ if (hadSelection) {
593
+ Transforms.deselect(slateEditor)
594
+ }
595
+
596
+ const childrenLength = slateEditor.children.length
597
+
598
+ slateEditor.children.forEach((_, index) => {
599
+ Transforms.removeNodes(slateEditor, {
600
+ at: [childrenLength - 1 - index],
601
+ })
602
+ })
603
+
604
+ Transforms.insertNodes(
605
+ slateEditor,
606
+ slateEditor.pteCreateTextBlock({decorators: []}),
607
+ {at: [0]},
608
+ )
609
+
610
+ // Add a new selection in the top of the document
611
+ if (hadSelection) {
612
+ Transforms.select(slateEditor, [0, 0])
613
+ }
614
+ })
615
+ })
616
+ })
617
+ })
618
+ }
619
+
620
+ /**
621
+ * Compare the length of the value and the length of the editor's children, and
622
+ * remove blocks that have become superfluous
623
+ */
595
624
  function removeExtraBlocks({
596
625
  slateEditor,
597
626
  value,
@@ -600,29 +629,26 @@ function removeExtraBlocks({
600
629
  value: Array<PortableTextBlock>
601
630
  }) {
602
631
  let isChanged = false
603
- const childrenLength = slateEditor.children.length
604
632
 
605
- // Remove blocks that have become superfluous
606
- if (value.length < childrenLength) {
607
- for (let i = childrenLength - 1; i > value.length - 1; i--) {
608
- Transforms.removeNodes(slateEditor, {
609
- at: [i],
633
+ Editor.withoutNormalizing(slateEditor, () => {
634
+ withRemoteChanges(slateEditor, () => {
635
+ withoutPatching(slateEditor, () => {
636
+ const childrenLength = slateEditor.children.length
637
+
638
+ if (value.length < childrenLength) {
639
+ for (let i = childrenLength - 1; i > value.length - 1; i--) {
640
+ Transforms.removeNodes(slateEditor, {
641
+ at: [i],
642
+ })
643
+ }
644
+
645
+ isChanged = true
646
+ }
610
647
  })
611
- }
612
- isChanged = true
613
- }
614
- return isChanged
615
- }
648
+ })
649
+ })
616
650
 
617
- async function* getStreamedBlocks({value}: {value: Array<PortableTextBlock>}) {
618
- let index = 0
619
- for await (const block of value) {
620
- if (index % 10 === 0) {
621
- await new Promise<void>((resolve) => setTimeout(resolve, 0))
622
- }
623
- yield [block, index] as const
624
- index++
625
- }
651
+ return isChanged
626
652
  }
627
653
 
628
654
  function syncBlock({
@@ -645,233 +671,306 @@ function syncBlock({
645
671
  slateEditor: PortableTextSlateEditor
646
672
  value: Array<PortableTextBlock>
647
673
  }) {
648
- let blockChanged = false
649
- let blockValid = true
650
- const currentBlock = block
651
- const currentBlockIndex = index
652
- const oldBlock = slateEditor.children[currentBlockIndex]
653
- const hasChanges = oldBlock && !isEqual(currentBlock, oldBlock)
674
+ const oldBlock = slateEditor.children.at(index)
675
+
676
+ if (!oldBlock) {
677
+ // Insert the new block
678
+ const validation = validateValue(
679
+ [block],
680
+ context.schema,
681
+ context.keyGenerator,
682
+ )
654
683
 
655
- Editor.withoutNormalizing(slateEditor, () => {
656
- withRemoteChanges(slateEditor, () => {
657
- withoutPatching(slateEditor, () => {
658
- if (hasChanges && blockValid) {
659
- const validationValue = [value[currentBlockIndex]]
660
- const validation = validateValue(
661
- validationValue,
662
- context.schema,
663
- context.keyGenerator,
664
- )
665
- // Resolve validations that can be resolved automatically, without involving the user (but only if the value was changed)
666
- if (
667
- !validation.valid &&
668
- validation.resolution?.autoResolve &&
669
- validation.resolution?.patches.length > 0
670
- ) {
671
- // Only apply auto resolution if the value has been populated before and is different from the last one.
672
- if (
673
- !context.readOnly &&
674
- context.previousValue &&
675
- context.previousValue !== value
676
- ) {
677
- // Give a console warning about the fact that it did an auto resolution
678
- console.warn(
679
- `${validation.resolution.action} for block with _key '${validationValue[0]._key}'. ${validation.resolution?.description}`,
680
- )
681
- validation.resolution.patches.forEach((patch) => {
682
- sendBack({type: 'patch', patch})
683
- })
684
- }
685
- }
686
- if (validation.valid || validation.resolution?.autoResolve) {
687
- const slateBlock = toSlateBlock(currentBlock, {
688
- schemaTypes: context.schema,
689
- })
684
+ if (debug.enabled)
685
+ debug('Validating and inserting new block in the end of the value', block)
690
686
 
691
- if (oldBlock._key === currentBlock._key) {
692
- if (debug.enabled) debug('Updating block', oldBlock, currentBlock)
693
- _updateBlock(slateEditor, slateBlock, oldBlock, currentBlockIndex)
694
- } else {
695
- if (debug.enabled)
696
- debug('Replacing block', oldBlock, currentBlock)
697
- _replaceBlock(slateEditor, slateBlock, currentBlockIndex)
698
- }
699
- blockChanged = true
700
- } else {
701
- sendBack({
702
- type: 'invalid value',
703
- resolution: validation.resolution,
704
- value,
705
- })
706
- blockValid = false
707
- }
708
- }
687
+ if (validation.valid || validation.resolution?.autoResolve) {
688
+ const slateBlock = toSlateBlock(block, {
689
+ schemaTypes: context.schema,
690
+ })
709
691
 
710
- if (!oldBlock && blockValid) {
711
- const validationValue = [currentBlock]
712
- const validation = validateValue(
713
- validationValue,
714
- context.schema,
715
- context.keyGenerator,
716
- )
717
- if (debug.enabled)
718
- debug(
719
- 'Validating and inserting new block in the end of the value',
720
- currentBlock,
721
- )
722
- if (validation.valid || validation.resolution?.autoResolve) {
723
- const slateBlock = toSlateBlock(currentBlock, {
724
- schemaTypes: context.schema,
725
- })
692
+ Editor.withoutNormalizing(slateEditor, () => {
693
+ withRemoteChanges(slateEditor, () => {
694
+ withoutPatching(slateEditor, () => {
726
695
  Transforms.insertNodes(slateEditor, slateBlock, {
727
- at: [currentBlockIndex],
696
+ at: [index],
728
697
  })
729
- } else {
730
- debug('Invalid', validation)
731
- sendBack({
732
- type: 'invalid value',
733
- resolution: validation.resolution,
734
- value,
698
+ })
699
+ })
700
+ })
701
+
702
+ return {
703
+ blockChanged: true,
704
+ blockValid: true,
705
+ }
706
+ }
707
+
708
+ debug('Invalid', validation)
709
+
710
+ sendBack({
711
+ type: 'invalid value',
712
+ resolution: validation.resolution,
713
+ value,
714
+ })
715
+
716
+ return {
717
+ blockChanged: false,
718
+ blockValid: false,
719
+ }
720
+ }
721
+
722
+ if (isEqual(block, oldBlock)) {
723
+ // Nothing to sync, skipping the block
724
+ return {
725
+ blockChanged: false,
726
+ blockValid: true,
727
+ }
728
+ }
729
+
730
+ const validationValue = [value[index]]
731
+ const validation = validateValue(
732
+ validationValue,
733
+ context.schema,
734
+ context.keyGenerator,
735
+ )
736
+
737
+ // Resolve validations that can be resolved automatically, without involving the user (but only if the value was changed)
738
+ if (
739
+ !validation.valid &&
740
+ validation.resolution?.autoResolve &&
741
+ validation.resolution?.patches.length > 0
742
+ ) {
743
+ // Only apply auto resolution if the value has been populated before and is different from the last one.
744
+ if (
745
+ !context.readOnly &&
746
+ context.previousValue &&
747
+ context.previousValue !== value
748
+ ) {
749
+ // Give a console warning about the fact that it did an auto resolution
750
+ console.warn(
751
+ `${validation.resolution.action} for block with _key '${validationValue[0]._key}'. ${validation.resolution?.description}`,
752
+ )
753
+ validation.resolution.patches.forEach((patch) => {
754
+ sendBack({type: 'patch', patch})
755
+ })
756
+ }
757
+ }
758
+
759
+ if (validation.valid || validation.resolution?.autoResolve) {
760
+ if (oldBlock._key === block._key) {
761
+ if (debug.enabled) debug('Updating block', oldBlock, block)
762
+
763
+ Editor.withoutNormalizing(slateEditor, () => {
764
+ withRemoteChanges(slateEditor, () => {
765
+ withoutPatching(slateEditor, () => {
766
+ updateBlock({
767
+ context,
768
+ slateEditor,
769
+ oldBlock,
770
+ block,
771
+ index,
735
772
  })
736
- blockValid = false
737
- }
738
- }
773
+ })
774
+ })
739
775
  })
776
+ } else {
777
+ if (debug.enabled) debug('Replacing block', oldBlock, block)
778
+
779
+ Editor.withoutNormalizing(slateEditor, () => {
780
+ withRemoteChanges(slateEditor, () => {
781
+ withoutPatching(slateEditor, () => {
782
+ replaceBlock({
783
+ context,
784
+ slateEditor,
785
+ block,
786
+ index,
787
+ })
788
+ })
789
+ })
790
+ })
791
+ }
792
+
793
+ return {
794
+ blockChanged: true,
795
+ blockValid: true,
796
+ }
797
+ } else {
798
+ sendBack({
799
+ type: 'invalid value',
800
+ resolution: validation.resolution,
801
+ value,
740
802
  })
741
- })
742
803
 
743
- return {blockChanged, blockValid}
804
+ return {
805
+ blockChanged: false,
806
+ blockValid: false,
807
+ }
808
+ }
744
809
  }
745
810
 
746
- /**
747
- * This code is moved out of the above algorithm to keep complexity down.
748
- * @internal
749
- */
750
- function _replaceBlock(
751
- slateEditor: PortableTextSlateEditor,
752
- currentBlock: Descendant,
753
- currentBlockIndex: number,
754
- ) {
811
+ function replaceBlock({
812
+ context,
813
+ slateEditor,
814
+ block,
815
+ index,
816
+ }: {
817
+ context: {
818
+ keyGenerator: () => string
819
+ previousValue: Array<PortableTextBlock> | undefined
820
+ readOnly: boolean
821
+ schema: EditorSchema
822
+ }
823
+ slateEditor: PortableTextSlateEditor
824
+ block: PortableTextBlock
825
+ index: number
826
+ }) {
827
+ const slateBlock = toSlateBlock(block, {
828
+ schemaTypes: context.schema,
829
+ })
830
+
755
831
  // While replacing the block and the current selection focus is on the replaced block,
756
832
  // temporarily deselect the editor then optimistically try to restore the selection afterwards.
757
833
  const currentSelection = slateEditor.selection
758
834
  const selectionFocusOnBlock =
759
- currentSelection && currentSelection.focus.path[0] === currentBlockIndex
835
+ currentSelection && currentSelection.focus.path[0] === index
836
+
760
837
  if (selectionFocusOnBlock) {
761
838
  Transforms.deselect(slateEditor)
762
839
  }
763
- Transforms.removeNodes(slateEditor, {at: [currentBlockIndex]})
764
- Transforms.insertNodes(slateEditor, currentBlock, {at: [currentBlockIndex]})
840
+
841
+ Transforms.removeNodes(slateEditor, {at: [index]})
842
+ Transforms.insertNodes(slateEditor, slateBlock, {at: [index]})
843
+
765
844
  slateEditor.onChange()
845
+
766
846
  if (selectionFocusOnBlock) {
767
847
  Transforms.select(slateEditor, currentSelection)
768
848
  }
769
849
  }
770
850
 
771
- /**
772
- * This code is moved out of the above algorithm to keep complexity down.
773
- * @internal
774
- */
775
- function _updateBlock(
776
- slateEditor: PortableTextSlateEditor,
777
- currentBlock: Descendant,
778
- oldBlock: Descendant,
779
- currentBlockIndex: number,
780
- ) {
851
+ function updateBlock({
852
+ context,
853
+ slateEditor,
854
+ oldBlock,
855
+ block,
856
+ index,
857
+ }: {
858
+ context: {
859
+ keyGenerator: () => string
860
+ previousValue: Array<PortableTextBlock> | undefined
861
+ readOnly: boolean
862
+ schema: EditorSchema
863
+ }
864
+ slateEditor: PortableTextSlateEditor
865
+ oldBlock: Descendant
866
+ block: PortableTextBlock
867
+ index: number
868
+ }) {
869
+ const slateBlock = toSlateBlock(block, {
870
+ schemaTypes: context.schema,
871
+ })
872
+
781
873
  // Update the root props on the block
782
- Transforms.setNodes(slateEditor, currentBlock as Partial<Node>, {
783
- at: [currentBlockIndex],
874
+ Transforms.setNodes(slateEditor, slateBlock as Partial<Node>, {
875
+ at: [index],
784
876
  })
877
+
785
878
  // Text block's need to have their children updated as well (setNode does not target a node's children)
786
879
  if (
787
- slateEditor.isTextBlock(currentBlock) &&
880
+ slateEditor.isTextBlock(slateBlock) &&
788
881
  slateEditor.isTextBlock(oldBlock)
789
882
  ) {
790
883
  const oldBlockChildrenLength = oldBlock.children.length
791
- if (currentBlock.children.length < oldBlockChildrenLength) {
884
+ if (slateBlock.children.length < oldBlockChildrenLength) {
792
885
  // Remove any children that have become superfluous
793
886
  Array.from(
794
- Array(oldBlockChildrenLength - currentBlock.children.length),
887
+ Array(oldBlockChildrenLength - slateBlock.children.length),
795
888
  ).forEach((_, index) => {
796
889
  const childIndex = oldBlockChildrenLength - 1 - index
890
+
797
891
  if (childIndex > 0) {
798
892
  debug('Removing child')
893
+
799
894
  Transforms.removeNodes(slateEditor, {
800
- at: [currentBlockIndex, childIndex],
895
+ at: [index, childIndex],
801
896
  })
802
897
  }
803
898
  })
804
899
  }
805
- currentBlock.children.forEach(
806
- (currentBlockChild, currentBlockChildIndex) => {
807
- const oldBlockChild = oldBlock.children[currentBlockChildIndex]
808
- const isChildChanged = !isEqual(currentBlockChild, oldBlockChild)
809
- const isTextChanged = !isEqual(
810
- currentBlockChild.text,
811
- oldBlockChild?.text,
812
- )
813
- const path = [currentBlockIndex, currentBlockChildIndex]
814
- if (isChildChanged) {
815
- // Update if this is the same child
816
- if (currentBlockChild._key === oldBlockChild?._key) {
817
- debug('Updating changed child', currentBlockChild, oldBlockChild)
900
+
901
+ slateBlock.children.forEach((currentBlockChild, currentBlockChildIndex) => {
902
+ const oldBlockChild = oldBlock.children[currentBlockChildIndex]
903
+ const isChildChanged = !isEqual(currentBlockChild, oldBlockChild)
904
+ const isTextChanged = !isEqual(
905
+ currentBlockChild.text,
906
+ oldBlockChild?.text,
907
+ )
908
+ const path = [index, currentBlockChildIndex]
909
+
910
+ if (isChildChanged) {
911
+ // Update if this is the same child
912
+ if (currentBlockChild._key === oldBlockChild?._key) {
913
+ debug('Updating changed child', currentBlockChild, oldBlockChild)
914
+
915
+ Transforms.setNodes(slateEditor, currentBlockChild as Partial<Node>, {
916
+ at: path,
917
+ })
918
+
919
+ const isSpanNode =
920
+ isSpan({schema: context.schema}, currentBlockChild) &&
921
+ isSpan({schema: context.schema}, oldBlockChild)
922
+
923
+ if (isSpanNode && isTextChanged) {
924
+ if (oldBlockChild.text.length > 0) {
925
+ deleteText(slateEditor, {
926
+ at: {
927
+ focus: {path, offset: 0},
928
+ anchor: {path, offset: oldBlockChild.text.length},
929
+ },
930
+ })
931
+ }
932
+
933
+ Transforms.insertText(slateEditor, currentBlockChild.text, {
934
+ at: path,
935
+ })
936
+
937
+ slateEditor.onChange()
938
+ } else if (!isSpanNode) {
939
+ // If it's a inline block, also update the void text node key
940
+ debug('Updating changed inline object child', currentBlockChild)
941
+
818
942
  Transforms.setNodes(
819
943
  slateEditor,
820
- currentBlockChild as Partial<Node>,
944
+ {_key: VOID_CHILD_KEY},
821
945
  {
822
- at: path,
946
+ at: [...path, 0],
947
+ voids: true,
823
948
  },
824
949
  )
825
- const isSpanNode =
826
- Text.isText(currentBlockChild) &&
827
- currentBlockChild._type === 'span' &&
828
- Text.isText(oldBlockChild) &&
829
- oldBlockChild._type === 'span'
830
- if (isSpanNode && isTextChanged) {
831
- if (oldBlockChild.text.length > 0) {
832
- deleteText(slateEditor, {
833
- at: {
834
- focus: {path, offset: 0},
835
- anchor: {path, offset: oldBlockChild.text.length},
836
- },
837
- })
838
- }
839
- Transforms.insertText(slateEditor, currentBlockChild.text, {
840
- at: path,
841
- })
842
- slateEditor.onChange()
843
- } else if (!isSpanNode) {
844
- // If it's a inline block, also update the void text node key
845
- debug('Updating changed inline object child', currentBlockChild)
846
- Transforms.setNodes(
847
- slateEditor,
848
- {_key: VOID_CHILD_KEY},
849
- {
850
- at: [...path, 0],
851
- voids: true,
852
- },
853
- )
854
- }
855
- // Replace the child if _key's are different
856
- } else if (oldBlockChild) {
857
- debug('Replacing child', currentBlockChild)
858
- Transforms.removeNodes(slateEditor, {
859
- at: [currentBlockIndex, currentBlockChildIndex],
860
- })
861
- Transforms.insertNodes(slateEditor, currentBlockChild as Node, {
862
- at: [currentBlockIndex, currentBlockChildIndex],
863
- })
864
- slateEditor.onChange()
865
- // Insert it if it didn't exist before
866
- } else if (!oldBlockChild) {
867
- debug('Inserting new child', currentBlockChild)
868
- Transforms.insertNodes(slateEditor, currentBlockChild as Node, {
869
- at: [currentBlockIndex, currentBlockChildIndex],
870
- })
871
- slateEditor.onChange()
872
950
  }
951
+ } else if (oldBlockChild) {
952
+ // Replace the child if _key's are different
953
+ debug('Replacing child', currentBlockChild)
954
+
955
+ Transforms.removeNodes(slateEditor, {
956
+ at: [index, currentBlockChildIndex],
957
+ })
958
+ Transforms.insertNodes(slateEditor, currentBlockChild as Node, {
959
+ at: [index, currentBlockChildIndex],
960
+ })
961
+
962
+ slateEditor.onChange()
963
+ } else if (!oldBlockChild) {
964
+ // Insert it if it didn't exist before
965
+ debug('Inserting new child', currentBlockChild)
966
+
967
+ Transforms.insertNodes(slateEditor, currentBlockChild as Node, {
968
+ at: [index, currentBlockChildIndex],
969
+ })
970
+
971
+ slateEditor.onChange()
873
972
  }
874
- },
875
- )
973
+ }
974
+ })
876
975
  }
877
976
  }