Skip to content

Commit

Permalink
fix: fix Original/Modified props issue. (#515)
Browse files Browse the repository at this point in the history
  • Loading branch information
jaywcjlove committed Jun 5, 2023
1 parent 8a5c149 commit 2a3efaf
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 28 deletions.
27 changes: 27 additions & 0 deletions merge/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,33 @@ export const Example = () => {
};
```

```jsx
import React, { useState } from 'react';
import CodeMirrorMerge from 'react-codemirror-merge';
import { EditorView } from '@codemirror/view';
import { javascript } from '@codemirror/lang-javascript';
import { githubLight, githubDark } from '@uiw/codemirror-theme-github';

const Original = CodeMirrorMerge.Original;
const Modified = CodeMirrorMerge.Modified;
let doc = `function examle() {
}`;

function Example() {
const [theme, setTheme] = useState('light');
return (
<div>
<CodeMirrorMerge theme={theme === 'light' ? githubLight : githubDark} orientation="a-b">
<Original extensions={[javascript({ jsx: true }), EditorView.lineWrapping]} value={doc} />
<Modified extensions={[EditorView.lineWrapping, javascript({ jsx: true })]} value={doc.replace(/e/g, 'T')} />
</CodeMirrorMerge>
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>Change Theme {theme}</button>
</div>
);
}
```

## Props

```ts
Expand Down
16 changes: 14 additions & 2 deletions merge/src/Internal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,20 @@ export const Internal = React.forwardRef<InternalRef, CodeMirrorMergeProps>((pro
if (view && original && modified && theme && editor.current && dispatch) {
editor.current.innerHTML = '';
new MergeView({
a: { ...original, extensions: [...(originalExtension || []), ...getDefaultExtensions({ theme: theme })] },
b: { ...modified, extensions: [...(modifiedExtension || []), ...getDefaultExtensions({ theme: theme })] },
a: {
...original,
extensions: [
...(originalExtension?.extension || []),
...getDefaultExtensions({ ...originalExtension?.option, theme }),
],
},
b: {
...modified,
extensions: [
...(modifiedExtension?.extension || []),
...getDefaultExtensions({ ...modifiedExtension?.option, theme }),
],
},
parent: editor.current,
...opts,
});
Expand Down
36 changes: 23 additions & 13 deletions merge/src/Modified.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ export interface ModifiedProps extends Omit<DefaultExtensionsOptions, 'theme'>,
}

export const Modified = (props: ModifiedProps): JSX.Element | null => {
const { extensions = [], selection, onChange, ...otherOption } = props;
const { extensions = [], value, selection, onChange, ...otherOption } = props;
const { modified, view, theme, dispatch } = useStore();
const defaultExtensions = getDefaultExtensions({ ...otherOption, theme });
const defaultExtensionsOptions = { ...otherOption };
const defaultExtensions = getDefaultExtensions({ ...defaultExtensionsOptions, theme });
const updateListener = EditorView.updateListener.of((vu: ViewUpdate) => {
if (
vu.docChanged &&
Expand All @@ -26,40 +27,49 @@ export const Modified = (props: ModifiedProps): JSX.Element | null => {
!vu.transactions.some((tr) => tr.annotation(External))
) {
const doc = vu.state.doc;
const value = doc.toString();
onChange(value, vu);
const val = doc.toString();
onChange(val, vu);
}
});
const extensionsData = [updateListener, ...defaultExtensions, ...extensions];
const data: EditorStateConfig = { extensions: [...extensionsData] };

useEffect(() => {
dispatch!({
modified: { doc: props.value, selection: selection, ...data },
modifiedExtension: [updateListener, extensions],
modified: { doc: value, selection: selection, ...data },
modifiedExtension: {
option: defaultExtensionsOptions,
extension: [updateListener, extensions],
},
});
}, []);

useEffect(() => dispatch!({ modifiedExtension: [updateListener, extensions] }), [extensions]);
useEffect(
() =>
dispatch!({
modifiedExtension: { option: otherOption, extension: [updateListener, extensions] },
}),
[props],
);

useEffect(() => {
if (modified?.doc !== props.value && view) {
data.doc = props.value;
dispatch!({ modified: { ...modified, ...data } });
if (modified?.doc !== value && view) {
data.doc = value;
const modifiedDoc = view?.b.state.doc.toString();
if (modifiedDoc !== props.value) {
if (modifiedDoc !== value) {
view.b.dispatch({
changes: { from: 0, to: (modifiedDoc || '').length, insert: props.value || '' },
changes: { from: 0, to: (modifiedDoc || '').length, insert: value || '' },
effects: StateEffect.reconfigure.of([...extensionsData]),
annotations: [External.of(true)],
});
}
dispatch!({ modified: { ...modified, ...data } });
}
if (modified?.selection !== selection) {
data.selection = selection;
dispatch!({ modified: { ...modified, ...data } });
}
}, [props.value, extensions, selection, view]);
}, [value, extensions, selection, view]);

return null;
};
Expand Down
34 changes: 23 additions & 11 deletions merge/src/Original.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export interface OriginalProps extends Omit<DefaultExtensionsOptions, 'theme'>,
}

export const Original = (props: OriginalProps): JSX.Element | null => {
const { extensions = [], selection, onChange, ...otherOption } = props;
const { extensions = [], value, selection, onChange, ...otherOption } = props;
const { original, view, theme, dispatch } = useStore();
const defaultExtensions = getDefaultExtensions({ ...otherOption, theme });
const updateListener = EditorView.updateListener.of((vu: ViewUpdate) => {
Expand All @@ -26,30 +26,42 @@ export const Original = (props: OriginalProps): JSX.Element | null => {
!vu.transactions.some((tr) => tr.annotation(External))
) {
const doc = vu.state.doc;
const value = doc.toString();
onChange(value, vu);
const val = doc.toString();
onChange(val, vu);
}
});
const extensionsData = [updateListener, ...defaultExtensions, ...extensions];
const data: EditorStateConfig = { extensions: [...extensionsData] };

useEffect(() => {
dispatch!({
original: { doc: props.value, selection: selection, ...data },
modifiedExtension: [updateListener, extensions],
original: { doc: value, selection: selection, ...data },
originalExtension: {
option: otherOption,
extension: [updateListener, extensions],
},
});
}, []);

useEffect(() => dispatch!({ originalExtension: [updateListener, extensions] }), [extensions]);
useEffect(
() =>
dispatch!({
originalExtension: {
option: otherOption,
extension: [updateListener, extensions],
},
}),
[props],
);

useEffect(() => {
if (original?.doc !== props.value && view) {
data.doc = props.value;
if (original?.doc !== value && view) {
data.doc = value;
dispatch!({ original: { ...original, ...data } });
const originalDoc = view?.a.state.doc.toString();
if (originalDoc !== props.value) {
if (originalDoc !== value) {
view?.a.dispatch({
changes: { from: 0, to: (originalDoc || '').length, insert: props.value || '' },
changes: { from: 0, to: (originalDoc || '').length, insert: value || '' },
effects: StateEffect.reconfigure.of([...extensionsData]),
annotations: [External.of(true)],
});
Expand All @@ -59,7 +71,7 @@ export const Original = (props: OriginalProps): JSX.Element | null => {
data.selection = selection;
dispatch!({ original: { ...original, ...data } });
}
}, [props.value, selection, view]);
}, [value, selection, view]);

return null;
};
Expand Down
11 changes: 9 additions & 2 deletions merge/src/store.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,22 @@ import React, { PropsWithChildren, createContext, useContext, useEffect, useRedu
import { EditorStateConfig } from '@codemirror/state';
import { MergeView, MergeConfig } from '@codemirror/merge';
import { Extension } from '@codemirror/state';
import { DefaultExtensionsOptions } from '@uiw/react-codemirror';

export interface StoreContextValue extends InitialState {
dispatch?: React.Dispatch<InitialState>;
}

export interface InitialState extends MergeConfig {
modifiedExtension?: Extension[];
modifiedExtension?: {
option: Omit<DefaultExtensionsOptions, 'theme'>;
extension: Extension[];
};
modified?: EditorStateConfig;
originalExtension?: Extension[];
originalExtension?: {
option: Omit<DefaultExtensionsOptions, 'theme'>;
extension: Extension[];
};
original?: EditorStateConfig;
view?: MergeView;
theme?: 'light' | 'dark' | 'none' | Extension;
Expand Down

0 comments on commit 2a3efaf

Please sign in to comment.