Skip to content

Commit

Permalink
feat: diffSourcePlugin readOnlyDiff parameter (#374)
Browse files Browse the repository at this point in the history
Co-authored-by: Stanislav Kubik <skubik@gohealth.com>
  • Loading branch information
StanlieK and Stanislav Kubik authored Mar 6, 2024
1 parent dcbd5cc commit 9867c6c
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 16 deletions.
37 changes: 37 additions & 0 deletions docs/diff-source.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,40 @@ It's an useful integration if you're building something for power users that are
]}
/>
```

## Read-Only Diff mode

You can enable the read-only mode for the diff viewer in two ways:

1. Use the `readOnly` flag on the `MDXEditor` - this makes the entire editor read-only, including both the source and rich-text modes.
2. Use the `readOnlyDiff` flag on the `diffSourcePlugin` - this makes only the diff mode read-only.

For example, the code below will display the differences but prevent code editing in diff view:

```tsx
<MDXEditor
markdown={'hello world'}
plugins={[
diffSourcePlugin({
diffMarkdown: 'An older version',
viewMode: 'diff',
readOnlyDiff: true
})
]}
/>
```

And this code will prevent any code changes in any mode:

```tsx
<MDXEditor
markdown={'hello world'}
readOnly={true}
plugins={[
diffSourcePlugin({
diffMarkdown: 'An older version',
viewMode: 'diff'
})
]}
/>
```
31 changes: 29 additions & 2 deletions src/examples/diff-source.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react'
import { DiffSourceToggleWrapper, MDXEditor, MDXEditorMethods, UndoRedo, diffSourcePlugin, toolbarPlugin } from '../'
import { DiffSourceToggleWrapper, MDXEditor, MDXEditorMethods, UndoRedo, diffSourcePlugin, headingsPlugin, toolbarPlugin } from '../'
import { useRef } from 'react'

export function GetMarkdownInSourceMode() {
Expand All @@ -17,7 +17,7 @@ export function GetMarkdownInSourceMode() {
)
}

export function ChangeDiffMakrkdown() {
export function ChangeDiffMarkdown() {
const ref = useRef<MDXEditorMethods>(null)
const [diffMarkdown, setDiffMarkdown] = React.useState('foo')
const [markdown] = React.useState('Hello world')
Expand Down Expand Up @@ -52,3 +52,30 @@ export function ChangeDiffMakrkdown() {
</div>
)
}

const markdown = `# Hello, Diff Mode!
This line is unchanged`

const oldMarkdown = `# Hello, World!
This line is unchanged`

export function ReadOnlyDiffMode() {
const ref = useRef<MDXEditorMethods>(null)
return (
<div className="App">
<MDXEditor
ref={ref}
markdown={markdown}
plugins={[
headingsPlugin(),
diffSourcePlugin({
viewMode: 'diff',
readOnlyDiff: true,
diffMarkdown: oldMarkdown
})
]}
/>
<button onClick={() => console.log(ref.current?.getMarkdown())}>Get Markdown</button>
</div>
)
}
32 changes: 22 additions & 10 deletions src/plugins/diff-source/DiffViewer.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react'

import { cmExtensions$, diffMarkdown$ } from '.'
import { markdown$, markdownSourceEditorValue$, onBlur$ } from '../core'
import { cmExtensions$, diffMarkdown$, readOnlyDiff$ } from '.'
import { markdown$, markdownSourceEditorValue$, onBlur$, readOnly$ } from '../core'

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

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

React.useEffect(() => {
const isReadOnly = readOnly || readOnlyDiff

const revertParams = isReadOnly
? ({
renderRevertControl: undefined,
revertControls: undefined
} as const)
: ({
renderRevertControl: () => {
const el = document.createElement('button')
el.classList.add('cm-merge-revert')
el.appendChild(document.createTextNode('\u2B95'))
return el
},
revertControls: 'a-to-b'
} as const)

cmMergeViewRef.current = new MergeView({
renderRevertControl: () => {
const el = document.createElement('button')
el.classList.add('cm-merge-revert')
el.appendChild(document.createTextNode('\u2B95'))
return el
},
...revertParams,
parent: elRef.current!,
orientation: 'a-b',
revertControls: 'a-to-b',
gutter: true,
a: {
doc: oldMarkdown,
Expand All @@ -57,6 +68,7 @@ export const DiffViewer: React.FC = () => {
extensions: [
...cmExtensions,
...COMMON_STATE_CONFIG_EXTENSIONS,
EditorState.readOnly.of(isReadOnly),
EditorView.updateListener.of(({ state }) => {
const md = state.doc.toString()
onUpdate(md)
Expand Down
17 changes: 13 additions & 4 deletions src/plugins/diff-source/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ export const diffMarkdown$ = Cell('')
/** @internal */
export const cmExtensions$ = Cell<Extension[]>([])

/** @internal */
export const readOnlyDiff$ = Cell(false)

/**
* @group Diff/Source
*/
Expand All @@ -28,17 +31,23 @@ export const diffSourcePlugin = realmPlugin<{
* Optional, additional CodeMirror extensions to load in the diff/source mode.
*/
codeMirrorExtensions?: Extension[]
/**
* Set the diff editor to read-only.
* @default false
*/
readOnlyDiff?: boolean
}>({
update: (r, params) => {
r.pub(diffMarkdown$, params?.diffMarkdown || '')
r.pub(diffMarkdown$, params?.diffMarkdown ?? '')
},

init(r, params) {
r.pubIn({
[diffMarkdown$]: params?.diffMarkdown || '',
[cmExtensions$]: params?.codeMirrorExtensions || [],
[diffMarkdown$]: params?.diffMarkdown ?? '',
[cmExtensions$]: params?.codeMirrorExtensions ?? [],
[addEditorWrapper$]: DiffSourceWrapper,
[viewMode$]: params?.viewMode || 'rich-text'
[readOnlyDiff$]: params?.readOnlyDiff ?? false,
[viewMode$]: params?.viewMode ?? 'rich-text'
})
}
})

0 comments on commit 9867c6c

Please sign in to comment.