refactor: improve chunk acceptance and rejection logic in CodeMirrorDiffUtils
- Simplified the acceptAllChunks and rejectAllChunks functions to handle document changes in a more robust manner. - Updated logic to merge changes in a single operation, addressing potential RangeErrors with empty originals. - Enhanced the CodeMirrorDiffView to conditionally apply themes based on the original document's content.
This commit is contained in:
parent
f4f02d5536
commit
cd4cb8e10b
2 changed files with 14 additions and 19 deletions
|
|
@ -42,15 +42,13 @@ export function acceptAllChunks(view: EditorView): boolean {
|
||||||
if (!result || result.chunks.length === 0) return false;
|
if (!result || result.chunks.length === 0) return false;
|
||||||
|
|
||||||
const orig = getOriginalDoc(view.state);
|
const orig = getOriginalDoc(view.state);
|
||||||
const specs: ChangeSpec[] = [];
|
// More robust than per-chunk: merge chunk ranges can be inconsistent for "empty" originals
|
||||||
for (const chunk of result.chunks) {
|
// (e.g. whitespace-only or reconstruction edge cases), which can throw RangeError.
|
||||||
specs.push({
|
// Accept-all semantics are simply: make original equal to current modified doc.
|
||||||
from: chunk.fromA,
|
const changes = ChangeSet.of(
|
||||||
to: chunk.toA,
|
[{ from: 0, to: orig.length, insert: view.state.doc.toString() }],
|
||||||
insert: view.state.doc.sliceString(chunk.fromB, chunk.toB),
|
orig.length
|
||||||
});
|
);
|
||||||
}
|
|
||||||
const changes = ChangeSet.of(specs, orig.length);
|
|
||||||
view.dispatch({
|
view.dispatch({
|
||||||
effects: updateOriginalDoc.of({ doc: changes.apply(orig), changes }),
|
effects: updateOriginalDoc.of({ doc: changes.apply(orig), changes }),
|
||||||
});
|
});
|
||||||
|
|
@ -63,15 +61,11 @@ export function rejectAllChunks(view: EditorView): boolean {
|
||||||
if (!result || result.chunks.length === 0) return false;
|
if (!result || result.chunks.length === 0) return false;
|
||||||
|
|
||||||
const orig = getOriginalDoc(view.state);
|
const orig = getOriginalDoc(view.state);
|
||||||
const specs: ChangeSpec[] = [];
|
// Same robustness principle as acceptAllChunks: reject-all semantics are simply
|
||||||
for (const chunk of result.chunks) {
|
// "restore the current doc to the original baseline" in one edit.
|
||||||
specs.push({
|
view.dispatch({
|
||||||
from: chunk.fromB,
|
changes: [{ from: 0, to: view.state.doc.length, insert: orig.toString() }],
|
||||||
to: chunk.toB,
|
});
|
||||||
insert: orig.sliceString(chunk.fromA, chunk.toA),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
view.dispatch({ changes: specs });
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -381,10 +381,11 @@ export const CodeMirrorDiffView = ({
|
||||||
);
|
);
|
||||||
|
|
||||||
const buildExtensions = useCallback(() => {
|
const buildExtensions = useCallback(() => {
|
||||||
|
const isEffectivelyEmptyOriginal = original.trim().length === 0;
|
||||||
const extensions: Extension[] = [
|
const extensions: Extension[] = [
|
||||||
baseEditorTheme,
|
baseEditorTheme,
|
||||||
diffSpecificTheme,
|
diffSpecificTheme,
|
||||||
...(original.length === 0 ? [emptyOriginalOverrideTheme] : []),
|
...(isEffectivelyEmptyOriginal ? [emptyOriginalOverrideTheme] : []),
|
||||||
lineNumbers(),
|
lineNumbers(),
|
||||||
syntaxHighlighting(oneDarkHighlightStyle),
|
syntaxHighlighting(oneDarkHighlightStyle),
|
||||||
EditorView.editable.of(!readOnly),
|
EditorView.editable.of(!readOnly),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue