mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-12 13:13:45 +01:00
[WEB] Only show affected lines plus one above/below in the diff viewer (#36052)
* adding trimmed diff view with context lines in unable-to-sync modal * addressing co pilot comments * Update services/web/frontend/js/features/ide-react/components/modals/diff-viewer.tsx Co-authored-by: Mathias Jakobsen <mathias.jakobsen@overleaf.com> --------- Co-authored-by: Mathias Jakobsen <mathias.jakobsen@overleaf.com> GitOrigin-RevId: de5a01048b0609288acf01196ff0a0f069e8bed3
This commit is contained in:
committed by
Copybot
co-authored by
Mathias Jakobsen
parent
98b79d9532
commit
b04bdd2944
@@ -1,5 +1,5 @@
|
||||
import { memo, useCallback, useMemo } from 'react'
|
||||
import { diffWordsWithSpace } from 'diff'
|
||||
import { diffWordsWithSpace, structuredPatch } from 'diff'
|
||||
|
||||
type DiffViewerProps = {
|
||||
baseContent: string
|
||||
@@ -7,36 +7,70 @@ type DiffViewerProps = {
|
||||
}
|
||||
|
||||
// Renders an inline diff between two document versions using <ins> and <del>
|
||||
// tags. This mirrors the DOM-based rendering approach used by the workbench
|
||||
// CodeDiff component (modules/workbench/frontend/js/components/code-diff.tsx).
|
||||
// tags. Only affected lines are shown (plus one line of context above/below),
|
||||
// with a separator between non-adjacent sections.
|
||||
// TODO: refactor both to share a common diff renderer from a shared location.
|
||||
function DiffViewer({ baseContent, targetContent }: DiffViewerProps) {
|
||||
const changes = useMemo(
|
||||
() => diffWordsWithSpace(baseContent, targetContent),
|
||||
[baseContent, targetContent]
|
||||
)
|
||||
const hunks = useMemo(() => {
|
||||
const patch = structuredPatch('', '', baseContent, targetContent, '', '', {
|
||||
context: 1,
|
||||
})
|
||||
|
||||
if (patch.hunks.length === 0) {
|
||||
return [diffWordsWithSpace(baseContent, targetContent)]
|
||||
}
|
||||
|
||||
return patch.hunks.map(hunk => {
|
||||
const baseLines: string[] = []
|
||||
const targetLines: string[] = []
|
||||
|
||||
for (const line of hunk.lines) {
|
||||
const content = line.slice(1)
|
||||
if (line[0] === '-') {
|
||||
baseLines.push(content)
|
||||
} else if (line[0] === '+') {
|
||||
targetLines.push(content)
|
||||
} else if (line[0] === ' ') {
|
||||
baseLines.push(content)
|
||||
targetLines.push(content)
|
||||
}
|
||||
}
|
||||
|
||||
return diffWordsWithSpace(baseLines.join('\n'), targetLines.join('\n'))
|
||||
})
|
||||
}, [baseContent, targetContent])
|
||||
|
||||
const createDiff = useCallback(
|
||||
(element: HTMLDivElement) => {
|
||||
if (!element) return
|
||||
element.replaceChildren()
|
||||
|
||||
for (const change of changes) {
|
||||
if (change.added) {
|
||||
const ins = document.createElement('ins')
|
||||
ins.textContent = change.value
|
||||
element.append(ins)
|
||||
} else if (change.removed) {
|
||||
const del = document.createElement('del')
|
||||
del.textContent = change.value
|
||||
element.append(del)
|
||||
} else {
|
||||
const text = document.createTextNode(change.value)
|
||||
element.append(text)
|
||||
for (let i = 0; i < hunks.length; i++) {
|
||||
if (i > 0) {
|
||||
const separator = document.createElement('div')
|
||||
separator.className = 'diff-separator'
|
||||
separator.setAttribute('aria-hidden', 'true')
|
||||
separator.textContent = '⋮'
|
||||
element.append(separator)
|
||||
}
|
||||
|
||||
for (const change of hunks[i]) {
|
||||
if (change.added) {
|
||||
const ins = document.createElement('ins')
|
||||
ins.textContent = change.value
|
||||
element.append(ins)
|
||||
} else if (change.removed) {
|
||||
const del = document.createElement('del')
|
||||
del.textContent = change.value
|
||||
element.append(del)
|
||||
} else {
|
||||
const text = document.createTextNode(change.value)
|
||||
element.append(text)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
[changes]
|
||||
[hunks]
|
||||
)
|
||||
|
||||
return <div className="diff-container" ref={createDiff} />
|
||||
|
||||
@@ -207,6 +207,13 @@ $editor-toggler-bg-dark-color: color.adjust(
|
||||
color: var(--red-50);
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.diff-separator {
|
||||
text-align: center;
|
||||
color: var(--content-secondary);
|
||||
padding: var(--spacing-01) 0;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user