Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ export function CodeMirrorDiffEditor({
const toggleLoadFullFiles = useDiffViewerStore((s) => s.toggleLoadFullFiles);
const wordDiffs = useDiffViewerStore((s) => s.wordDiffs);
const toggleWordDiffs = useDiffViewerStore((s) => s.toggleWordDiffs);
const hideWhitespaceChanges = useDiffViewerStore(
(s) => s.hideWhitespaceChanges,
);
const toggleHideWhitespaceChanges = useDiffViewerStore(
(s) => s.toggleHideWhitespaceChanges,
);
const extensions = useEditorExtensions(filePath, !onContentChange, true);
const options = useMemo(
() => ({
Expand All @@ -41,6 +47,7 @@ export function CodeMirrorDiffEditor({
mode: viewMode,
loadFullFiles,
wordDiffs,
hideWhitespaceChanges,
filePath,
onContentChange,
}),
Expand All @@ -51,6 +58,7 @@ export function CodeMirrorDiffEditor({
viewMode,
loadFullFiles,
wordDiffs,
hideWhitespaceChanges,
filePath,
onContentChange,
],
Expand Down Expand Up @@ -127,6 +135,11 @@ export function CodeMirrorDiffEditor({
{wordDiffs ? "Disable word diffs" : "Enable word diffs"}
</Text>
</DropdownMenu.Item>
<DropdownMenu.Item onSelect={toggleHideWhitespaceChanges}>
<Text size="1">
{hideWhitespaceChanges ? "Show whitespace" : "Hide whitespace"}
</Text>
</DropdownMenu.Item>

{onRefresh && (
<>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { MergeView, unifiedMergeView } from "@codemirror/merge";
import {
diff as defaultDiff,
MergeView,
unifiedMergeView,
} from "@codemirror/merge";
import { EditorState, type Extension } from "@codemirror/state";
import { EditorView } from "@codemirror/view";
import { workspaceApi } from "@features/workspace/hooks/useWorkspace";
Expand All @@ -24,6 +28,7 @@ interface DiffOptions extends UseCodeMirrorOptions {
mode: "split" | "unified";
loadFullFiles?: boolean;
wordDiffs?: boolean;
hideWhitespaceChanges?: boolean;
onContentChange?: (content: string) => void;
}

Expand Down Expand Up @@ -62,15 +67,28 @@ const createMergeControls = (onReject?: () => void) => {
};
};

const whitespaceIgnoringDiff = (a: string, b: string) => {
const changes = defaultDiff(a, b);
return changes.filter((change) => {
const textA = a.slice(change.fromA, change.toA);
const textB = b.slice(change.fromB, change.toB);
return textA.replace(/\s/g, "") !== textB.replace(/\s/g, "");
});
};

const collapseExtension = (loadFullFiles?: boolean): Extension =>
loadFullFiles ? [] : gradualCollapseUnchanged({ margin: 3, minSize: 4 });

const getBaseDiffConfig = (
hideWhitespaceChanges?: boolean,
onReject?: () => void,
): Partial<Parameters<typeof unifiedMergeView>[0]> => ({
highlightChanges: false,
gutter: true,
mergeControls: createMergeControls(onReject),
diffConfig: hideWhitespaceChanges
? { override: whitespaceIgnoringDiff }
: undefined,
});

export function useCodeMirror(options: SingleDocOptions | DiffOptions) {
Expand All @@ -93,6 +111,7 @@ export function useCodeMirror(options: SingleDocOptions | DiffOptions) {
});
} else if (options.mode === "split") {
const diffConfig = getBaseDiffConfig(
options.hideWhitespaceChanges,
options.onContentChange
? () => {
if (instanceRef.current instanceof MergeView) {
Expand Down Expand Up @@ -143,6 +162,7 @@ export function useCodeMirror(options: SingleDocOptions | DiffOptions) {
});
} else {
const diffConfig = getBaseDiffConfig(
options.hideWhitespaceChanges,
options.onContentChange
? () => {
if (instanceRef.current instanceof EditorView) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ interface DiffViewerStoreState {
wordWrap: boolean;
loadFullFiles: boolean;
wordDiffs: boolean;
hideWhitespaceChanges: boolean;
}

interface DiffViewerStoreActions {
Expand All @@ -16,6 +17,7 @@ interface DiffViewerStoreActions {
toggleWordWrap: () => void;
toggleLoadFullFiles: () => void;
toggleWordDiffs: () => void;
toggleHideWhitespaceChanges: () => void;
}

type DiffViewerStore = DiffViewerStoreState & DiffViewerStoreActions;
Expand All @@ -27,6 +29,7 @@ export const useDiffViewerStore = create<DiffViewerStore>()(
wordWrap: true,
loadFullFiles: false,
wordDiffs: false,
hideWhitespaceChanges: false,
setViewMode: (mode) => set({ viewMode: mode }),
toggleViewMode: () =>
set((s) => ({
Expand All @@ -36,6 +39,8 @@ export const useDiffViewerStore = create<DiffViewerStore>()(
toggleLoadFullFiles: () =>
set((s) => ({ loadFullFiles: !s.loadFullFiles })),
toggleWordDiffs: () => set((s) => ({ wordDiffs: !s.wordDiffs })),
toggleHideWhitespaceChanges: () =>
set((s) => ({ hideWhitespaceChanges: !s.hideWhitespaceChanges })),
}),
{
name: "diff-viewer-storage",
Expand Down
Loading