1
1
import React , { useEffect , useImperativeHandle , useRef } from 'react' ;
2
- import { EditorStateConfig } from '@codemirror/state' ;
2
+ import { EditorStateConfig , StateEffect } from '@codemirror/state' ;
3
3
import { getDefaultExtensions } from '@uiw/react-codemirror' ;
4
4
import { MergeView , MergeConfig , DirectMergeConfig } from '@codemirror/merge' ;
5
5
import { useStore } from './store' ;
@@ -25,15 +25,16 @@ export const Internal = React.forwardRef<InternalRef, CodeMirrorMergeProps>((pro
25
25
renderRevertControl,
26
26
...elmProps
27
27
} = props ;
28
- const { modified, modifiedExtension, original, originalExtension, theme, view , dispatch, ...otherStore } = useStore ( ) ;
28
+ const { modified, modifiedExtension, original, originalExtension, theme, dispatch, ...otherStore } = useStore ( ) ;
29
29
const editor = useRef < HTMLDivElement > ( null ) ;
30
+ const view = useRef < MergeView > ( ) ;
30
31
const opts = { orientation, revertControls, highlightChanges, gutter, collapseUnchanged, renderRevertControl } ;
31
32
32
33
useImperativeHandle (
33
34
ref ,
34
35
( ) => ( {
35
36
container : editor . current ,
36
- view,
37
+ view : view . current ,
37
38
modified,
38
39
original,
39
40
config : {
@@ -47,9 +48,8 @@ export const Internal = React.forwardRef<InternalRef, CodeMirrorMergeProps>((pro
47
48
) ;
48
49
49
50
useEffect ( ( ) => {
50
- if ( view && original && modified && theme && editor . current && dispatch ) {
51
- editor . current . innerHTML = '' ;
52
- new MergeView ( {
51
+ if ( ! view . current && editor . current ) {
52
+ view . current = new MergeView ( {
53
53
a : {
54
54
...original ,
55
55
extensions : [
@@ -68,24 +68,58 @@ export const Internal = React.forwardRef<InternalRef, CodeMirrorMergeProps>((pro
68
68
...opts ,
69
69
} ) ;
70
70
}
71
- } , [ theme , editor . current , original , modified , originalExtension , modifiedExtension ] ) ;
71
+ } , [ view , editor ] ) ;
72
72
73
73
useEffect ( ( ) => {
74
- if ( ! view && editor . current && original ?. extensions && modified ?. extensions ) {
75
- const viewDefault = new MergeView ( {
76
- a : original ,
77
- b : modified ,
78
- parent : editor . current ,
79
- ...opts ,
80
- } ) ;
81
- dispatch && dispatch ( { view : viewDefault , container : editor . current , ...opts } ) ;
74
+ if ( original && original . doc && view . current ) {
75
+ const originalDoc = view . current ?. a . state . doc . toString ( ) ;
76
+ if ( originalDoc !== original . doc ) {
77
+ view . current ?. a . dispatch ( {
78
+ changes : { from : 0 , to : originalDoc . length , insert : original . doc || '' } ,
79
+ // effects: StateEffect.reconfigure.of([
80
+ // ...(originalExtension?.extension || []),
81
+ // ...getDefaultExtensions({ ...originalExtension?.option, theme }),
82
+ // ])
83
+ } ) ;
84
+ }
82
85
}
83
- } , [ editor . current , original , modified , view ] ) ;
86
+ if ( modified && modified . doc && view . current ) {
87
+ const modifiedDoc = view . current ?. b . state . doc . toString ( ) ;
88
+ if ( modifiedDoc !== modified . doc ) {
89
+ view . current ?. b . dispatch ( {
90
+ changes : { from : 0 , to : modifiedDoc . length , insert : modified . doc || '' } ,
91
+ // effects: StateEffect.reconfigure.of([
92
+ // ...(modifiedExtension?.extension || []),
93
+ // ...getDefaultExtensions({ ...modifiedExtension?.option, theme }),
94
+ // ])
95
+ } ) ;
96
+ }
97
+ }
98
+ view . current ?. destroy ( ) ;
99
+ view . current = new MergeView ( {
100
+ a : {
101
+ ...original ,
102
+ extensions : [
103
+ ...( originalExtension ?. extension || [ ] ) ,
104
+ ...getDefaultExtensions ( { ...originalExtension ?. option , theme } ) ,
105
+ ] ,
106
+ } ,
107
+ b : {
108
+ ...modified ,
109
+ extensions : [
110
+ ...( modifiedExtension ?. extension || [ ] ) ,
111
+ ...getDefaultExtensions ( { ...modifiedExtension ?. option , theme } ) ,
112
+ ] ,
113
+ } ,
114
+ parent : editor . current ! ,
115
+ ...opts ,
116
+ } ) ;
117
+ } , [ view , theme , editor . current , original , modified , originalExtension , modifiedExtension ] ) ;
84
118
85
- useEffect ( ( ) => ( ) => view && view . destroy ( ) , [ ] ) ;
119
+ useEffect ( ( ) => ( ) => view . current && view . current . destroy ( ) , [ ] ) ;
86
120
87
121
useEffect ( ( ) => {
88
- if ( view ) {
122
+ if ( view . current ) {
89
123
const opts : MergeConfig = { } ;
90
124
if ( otherStore . orientation !== orientation ) {
91
125
opts . orientation = orientation ;
@@ -102,29 +136,15 @@ export const Internal = React.forwardRef<InternalRef, CodeMirrorMergeProps>((pro
102
136
if ( otherStore . collapseUnchanged !== collapseUnchanged ) {
103
137
opts . collapseUnchanged = collapseUnchanged ;
104
138
}
105
- if ( Object . keys ( opts ) . length && dispatch && original && modified && editor . current ) {
106
- view . destroy ( ) ;
107
- const viewDefault = new MergeView ( {
108
- a : original ,
109
- b : modified ,
110
- parent : editor . current ,
111
- ...opts ,
112
- } ) ;
113
- dispatch ( { ...opts , renderRevertControl, view : viewDefault } ) ;
139
+ if ( otherStore . renderRevertControl !== renderRevertControl ) {
140
+ opts . collapseUnchanged = collapseUnchanged ;
141
+ }
142
+ if ( Object . keys ( opts ) . length && dispatch && view . current ) {
143
+ view . current . reconfigure ( { ...opts } ) ;
144
+ dispatch ( { ...opts } ) ;
114
145
}
115
146
}
116
- } , [
117
- view ,
118
- original ,
119
- modified ,
120
- editor ,
121
- orientation ,
122
- revertControls ,
123
- highlightChanges ,
124
- gutter ,
125
- collapseUnchanged ,
126
- renderRevertControl ,
127
- ] ) ;
147
+ } , [ dispatch , view , orientation , revertControls , highlightChanges , gutter , collapseUnchanged , renderRevertControl ] ) ;
128
148
129
149
const defaultClassNames = 'cm-merge-theme' ;
130
150
return (
0 commit comments