Skip to content

Commit 9867c6c

Browse files
StanlieKStanislav Kubik
and
Stanislav Kubik
authored
feat: diffSourcePlugin readOnlyDiff parameter (#374)
Co-authored-by: Stanislav Kubik <[email protected]>
1 parent dcbd5cc commit 9867c6c

File tree

4 files changed

+101
-16
lines changed

4 files changed

+101
-16
lines changed

docs/diff-source.md

+37
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,40 @@ It's an useful integration if you're building something for power users that are
2727
]}
2828
/>
2929
```
30+
31+
## Read-Only Diff mode
32+
33+
You can enable the read-only mode for the diff viewer in two ways:
34+
35+
1. Use the `readOnly` flag on the `MDXEditor` - this makes the entire editor read-only, including both the source and rich-text modes.
36+
2. Use the `readOnlyDiff` flag on the `diffSourcePlugin` - this makes only the diff mode read-only.
37+
38+
For example, the code below will display the differences but prevent code editing in diff view:
39+
40+
```tsx
41+
<MDXEditor
42+
markdown={'hello world'}
43+
plugins={[
44+
diffSourcePlugin({
45+
diffMarkdown: 'An older version',
46+
viewMode: 'diff',
47+
readOnlyDiff: true
48+
})
49+
]}
50+
/>
51+
```
52+
53+
And this code will prevent any code changes in any mode:
54+
55+
```tsx
56+
<MDXEditor
57+
markdown={'hello world'}
58+
readOnly={true}
59+
plugins={[
60+
diffSourcePlugin({
61+
diffMarkdown: 'An older version',
62+
viewMode: 'diff'
63+
})
64+
]}
65+
/>
66+
```

src/examples/diff-source.tsx

+29-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react'
2-
import { DiffSourceToggleWrapper, MDXEditor, MDXEditorMethods, UndoRedo, diffSourcePlugin, toolbarPlugin } from '../'
2+
import { DiffSourceToggleWrapper, MDXEditor, MDXEditorMethods, UndoRedo, diffSourcePlugin, headingsPlugin, toolbarPlugin } from '../'
33
import { useRef } from 'react'
44

55
export function GetMarkdownInSourceMode() {
@@ -17,7 +17,7 @@ export function GetMarkdownInSourceMode() {
1717
)
1818
}
1919

20-
export function ChangeDiffMakrkdown() {
20+
export function ChangeDiffMarkdown() {
2121
const ref = useRef<MDXEditorMethods>(null)
2222
const [diffMarkdown, setDiffMarkdown] = React.useState('foo')
2323
const [markdown] = React.useState('Hello world')
@@ -52,3 +52,30 @@ export function ChangeDiffMakrkdown() {
5252
</div>
5353
)
5454
}
55+
56+
const markdown = `# Hello, Diff Mode!
57+
This line is unchanged`
58+
59+
const oldMarkdown = `# Hello, World!
60+
This line is unchanged`
61+
62+
export function ReadOnlyDiffMode() {
63+
const ref = useRef<MDXEditorMethods>(null)
64+
return (
65+
<div className="App">
66+
<MDXEditor
67+
ref={ref}
68+
markdown={markdown}
69+
plugins={[
70+
headingsPlugin(),
71+
diffSourcePlugin({
72+
viewMode: 'diff',
73+
readOnlyDiff: true,
74+
diffMarkdown: oldMarkdown
75+
})
76+
]}
77+
/>
78+
<button onClick={() => console.log(ref.current?.getMarkdown())}>Get Markdown</button>
79+
</div>
80+
)
81+
}

src/plugins/diff-source/DiffViewer.tsx

+22-10
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react'
22

3-
import { cmExtensions$, diffMarkdown$ } from '.'
4-
import { markdown$, markdownSourceEditorValue$, onBlur$ } from '../core'
3+
import { cmExtensions$, diffMarkdown$, readOnlyDiff$ } from '.'
4+
import { markdown$, markdownSourceEditorValue$, onBlur$, readOnly$ } from '../core'
55

66
import { MergeView } from '@codemirror/merge'
77
import { EditorState } from '@codemirror/state'
@@ -17,7 +17,7 @@ function setContent(view: EditorView | undefined, content: string) {
1717

1818
export const DiffViewer: React.FC = () => {
1919
const realm = useRealm()
20-
const [newMarkdown, oldMarkdown] = useCellValues(markdown$, diffMarkdown$)
20+
const [newMarkdown, oldMarkdown, readOnly, readOnlyDiff] = useCellValues(markdown$, diffMarkdown$, readOnly$, readOnlyDiff$)
2121
const onUpdate = usePublisher(markdownSourceEditorValue$)
2222
const elRef = React.useRef<HTMLDivElement | null>(null)
2323
const cmMergeViewRef = React.useRef<MergeView | null>(null)
@@ -37,16 +37,27 @@ export const DiffViewer: React.FC = () => {
3737
}, [realm])
3838

3939
React.useEffect(() => {
40+
const isReadOnly = readOnly || readOnlyDiff
41+
42+
const revertParams = isReadOnly
43+
? ({
44+
renderRevertControl: undefined,
45+
revertControls: undefined
46+
} as const)
47+
: ({
48+
renderRevertControl: () => {
49+
const el = document.createElement('button')
50+
el.classList.add('cm-merge-revert')
51+
el.appendChild(document.createTextNode('\u2B95'))
52+
return el
53+
},
54+
revertControls: 'a-to-b'
55+
} as const)
56+
4057
cmMergeViewRef.current = new MergeView({
41-
renderRevertControl: () => {
42-
const el = document.createElement('button')
43-
el.classList.add('cm-merge-revert')
44-
el.appendChild(document.createTextNode('\u2B95'))
45-
return el
46-
},
58+
...revertParams,
4759
parent: elRef.current!,
4860
orientation: 'a-b',
49-
revertControls: 'a-to-b',
5061
gutter: true,
5162
a: {
5263
doc: oldMarkdown,
@@ -57,6 +68,7 @@ export const DiffViewer: React.FC = () => {
5768
extensions: [
5869
...cmExtensions,
5970
...COMMON_STATE_CONFIG_EXTENSIONS,
71+
EditorState.readOnly.of(isReadOnly),
6072
EditorView.updateListener.of(({ state }) => {
6173
const md = state.doc.toString()
6274
onUpdate(md)

src/plugins/diff-source/index.tsx

+13-4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ export const diffMarkdown$ = Cell('')
1010
/** @internal */
1111
export const cmExtensions$ = Cell<Extension[]>([])
1212

13+
/** @internal */
14+
export const readOnlyDiff$ = Cell(false)
15+
1316
/**
1417
* @group Diff/Source
1518
*/
@@ -28,17 +31,23 @@ export const diffSourcePlugin = realmPlugin<{
2831
* Optional, additional CodeMirror extensions to load in the diff/source mode.
2932
*/
3033
codeMirrorExtensions?: Extension[]
34+
/**
35+
* Set the diff editor to read-only.
36+
* @default false
37+
*/
38+
readOnlyDiff?: boolean
3139
}>({
3240
update: (r, params) => {
33-
r.pub(diffMarkdown$, params?.diffMarkdown || '')
41+
r.pub(diffMarkdown$, params?.diffMarkdown ?? '')
3442
},
3543

3644
init(r, params) {
3745
r.pubIn({
38-
[diffMarkdown$]: params?.diffMarkdown || '',
39-
[cmExtensions$]: params?.codeMirrorExtensions || [],
46+
[diffMarkdown$]: params?.diffMarkdown ?? '',
47+
[cmExtensions$]: params?.codeMirrorExtensions ?? [],
4048
[addEditorWrapper$]: DiffSourceWrapper,
41-
[viewMode$]: params?.viewMode || 'rich-text'
49+
[readOnlyDiff$]: params?.readOnlyDiff ?? false,
50+
[viewMode$]: params?.viewMode ?? 'rich-text'
4251
})
4352
}
4453
})

0 commit comments

Comments
 (0)