Skip to content

Commit 6ecf1b8

Browse files
wip
1 parent f56ecb2 commit 6ecf1b8

File tree

4 files changed

+602
-0
lines changed

4 files changed

+602
-0
lines changed
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
<script lang="ts">
2+
import { getEnableAddWidget } from '$lib/context/enableAddWidget.js';
3+
import { getEnableHighlight } from '$lib/context/enableHighlight.js';
4+
import { getOnAddWidgetClick } from '$lib/context/onAddWidgetClick.js';
5+
import { getWidget } from '$lib/context/widget.js';
6+
import {
7+
checkDiffLineIncludeChange,
8+
DiffLineType,
9+
SplitSide,
10+
type DiffFile
11+
} from '@git-diff-view/core';
12+
import {
13+
diffAsideWidthName,
14+
emptyBGName,
15+
expandLineNumberColorName,
16+
getContentBG,
17+
getLineNumberBG,
18+
plainLineNumberColorName
19+
} from '@git-diff-view/utils';
20+
import DiffSplitAddWidget from './DiffSplitAddWidget.svelte';
21+
import DiffContent from './DiffContent.svelte';
22+
23+
interface Props {
24+
index: number;
25+
side: SplitSide;
26+
diffFile: DiffFile;
27+
lineNumber: number;
28+
}
29+
30+
let props: Props = $props();
31+
32+
const widget = $derived.by(getWidget());
33+
34+
const enableAddWidget = $derived.by(getEnableAddWidget());
35+
36+
const enableHighlight = $derived.by(getEnableHighlight());
37+
38+
const onAddWidgetClick = $derived.by(getOnAddWidgetClick());
39+
40+
const currentLine = $derived.by(() =>
41+
props.side === SplitSide.old
42+
? props.diffFile.getSplitLeftLine(props.index)
43+
: props.diffFile.getSplitRightLine(props.index)
44+
);
45+
46+
const currentLineHasDiff = $derived.by(() => !!currentLine?.diff);
47+
48+
const currentLineHasChange = $derived.by(() => checkDiffLineIncludeChange(currentLine?.diff));
49+
50+
const currentLineHasHidden = $derived.by(() => currentLine?.isHidden);
51+
52+
const currentLineHasContent = $derived.by(() => !!currentLine?.lineNumber);
53+
54+
const getCurrentSyntaxLine = () =>
55+
props.side === SplitSide.old
56+
? props.diffFile.getOldSyntaxLine(currentLine?.lineNumber || 0)
57+
: props.diffFile.getNewSyntaxLine(currentLine?.lineNumber || 0);
58+
59+
const getCurrentPlainLine = () =>
60+
props.side === SplitSide.old
61+
? props.diffFile.getOldPlainLine(currentLine?.lineNumber || 0)
62+
: props.diffFile.getNewPlainLine(currentLine?.lineNumber || 0);
63+
64+
let currentSyntaxLine = $state(getCurrentSyntaxLine());
65+
66+
let currentPlainLine = $state(getCurrentPlainLine());
67+
68+
const init = () => {
69+
currentSyntaxLine = getCurrentSyntaxLine();
70+
currentPlainLine = getCurrentPlainLine();
71+
};
72+
73+
let unSubscribe = { current: () => {} };
74+
75+
$effect(() => {
76+
unSubscribe.current();
77+
78+
init();
79+
80+
unSubscribe.current = props.diffFile.subscribe(init);
81+
});
82+
83+
const onOpenAddWidget = (lineNumber: number, side: SplitSide) => {
84+
widget.side = side;
85+
widget.lineNumber = lineNumber;
86+
};
87+
88+
const isAdded = () => currentLine?.diff?.type === DiffLineType.Add;
89+
90+
const isDelete = () => currentLine?.diff?.type === DiffLineType.Delete;
91+
</script>
92+
93+
{#if !currentLineHasHidden}
94+
<tr
95+
data-line={props.lineNumber}
96+
data-state={currentLineHasDiff || !currentLineHasContent ? 'diff' : 'plain'}
97+
data-side={SplitSide[props.side]}
98+
class={'diff-line' + (currentLineHasContent ? ' group' : '')}
99+
>
100+
{#if currentLineHasContent}
101+
<td
102+
class={`diff-line-${SplitSide[props.side]}-num sticky left-0 z-[1] w-[1%] min-w-[40px] select-none pl-[10px] pr-[10px] text-right align-top`}
103+
style={`
104+
background-color: ${getLineNumberBG(isAdded(), isDelete(), currentLineHasDiff)},
105+
color: var(${currentLineHasDiff ? plainLineNumberColorName : expandLineNumberColorName}),
106+
width: var(${diffAsideWidthName}),
107+
min-width': var(${diffAsideWidthName}),
108+
max-width': var(${diffAsideWidthName})
109+
`}
110+
>
111+
{#if currentLineHasDiff && enableAddWidget}
112+
<DiffSplitAddWidget
113+
index={props.index}
114+
lineNumber={currentLine?.lineNumber || 0}
115+
side={props.side}
116+
diffFile={props.diffFile}
117+
onWidgetClick={onAddWidgetClick}
118+
className="absolute left-[100%] z-[1] translate-x-[-50%]"
119+
{onOpenAddWidget}
120+
/>
121+
{/if}
122+
<span
123+
data-line-num={currentLine?.lineNumber}
124+
style={` opacity: ${currentLineHasChange ? undefined : 0.5} `}
125+
>
126+
{currentLine?.lineNumber}
127+
</span>
128+
</td>
129+
<td
130+
class={`diff-line-${SplitSide[props.side]}-content pr-[10px] align-top`}
131+
style={` background-color: ${getContentBG(isAdded(), isDelete(), currentLineHasDiff)} `}
132+
>
133+
<DiffContent
134+
enableWrap={false}
135+
diffFile={props.diffFile}
136+
rawLine={currentLine?.value || ''}
137+
diffLine={currentLine?.diff}
138+
plainLine={currentPlainLine}
139+
syntaxLine={currentSyntaxLine}
140+
enableHighlight={!!enableHighlight}
141+
/>
142+
</td>
143+
{:else}
144+
<td
145+
class={`diff-line-${SplitSide[props.side]}-placeholder select-none`}
146+
style={`background-color': var(${emptyBGName}) `}
147+
colspan={2}
148+
>
149+
<span>&ensp;</span>
150+
</td>
151+
{/if}
152+
</tr>
153+
{/if}
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
<script lang="ts">
2+
import { getEnableAddWidget } from '$lib/context/enableAddWidget.js';
3+
import { getEnableHighlight } from '$lib/context/enableHighlight.js';
4+
import { getOnAddWidgetClick } from '$lib/context/onAddWidgetClick.js';
5+
import { getWidget } from '$lib/context/widget.js';
6+
import {
7+
checkDiffLineIncludeChange,
8+
DiffLineType,
9+
SplitSide,
10+
type DiffFile
11+
} from '@git-diff-view/core';
12+
import {
13+
borderColorName,
14+
emptyBGName,
15+
expandLineNumberColorName,
16+
getContentBG,
17+
getLineNumberBG,
18+
plainLineNumberColorName
19+
} from '@git-diff-view/utils';
20+
import DiffSplitAddWidget from './DiffSplitAddWidget.svelte';
21+
import DiffContent from './DiffContent.svelte';
22+
23+
interface Props {
24+
index: number;
25+
diffFile: DiffFile;
26+
lineNumber: number;
27+
}
28+
29+
let props: Props = $props();
30+
31+
const widget = $derived.by(getWidget());
32+
33+
const enableAddWidget = $derived.by(getEnableAddWidget());
34+
35+
const enableHighlight = $derived.by(getEnableHighlight());
36+
37+
const onAddWidgetClick = $derived.by(getOnAddWidgetClick());
38+
39+
const oldLine = $derived.by(() => props.diffFile.getSplitLeftLine(props.index));
40+
41+
const newLine = $derived.by(() => props.diffFile.getSplitRightLine(props.index));
42+
43+
const getOldSyntaxLine = () => props.diffFile.getOldSyntaxLine(oldLine?.lineNumber || 0);
44+
45+
const getNewSyntaxLine = () => props.diffFile.getNewSyntaxLine(newLine?.lineNumber || 0);
46+
47+
const getOldPlainLine = () => props.diffFile.getOldPlainLine(oldLine?.lineNumber || 0);
48+
49+
const getNewPlainLine = () => props.diffFile.getNewPlainLine(newLine?.lineNumber || 0);
50+
51+
let oldSyntaxLine = $state(getOldSyntaxLine());
52+
53+
let newSyntaxLine = $state(getNewSyntaxLine());
54+
55+
let oldPlainLine = $state(getOldPlainLine());
56+
57+
let newPlainLine = $state(getNewPlainLine());
58+
59+
const hasDiff = $derived.by(() => !!oldLine?.diff || !!newLine?.diff);
60+
61+
const hasChange = $derived.by(
62+
() => checkDiffLineIncludeChange(oldLine?.diff) || checkDiffLineIncludeChange(newLine?.diff)
63+
);
64+
65+
const hasHidden = $derived.by(() => oldLine?.isHidden && newLine?.isHidden);
66+
67+
const oldLineIsDelete = () => oldLine?.diff?.type === DiffLineType.Delete;
68+
69+
const newLineIsAdded = () => newLine?.diff?.type === DiffLineType.Add;
70+
71+
const init = () => {
72+
oldSyntaxLine = getOldSyntaxLine();
73+
newSyntaxLine = getNewSyntaxLine();
74+
oldPlainLine = getOldPlainLine();
75+
newPlainLine = getNewPlainLine();
76+
};
77+
78+
const unSubscribe = { current: () => {} };
79+
80+
$effect(() => {
81+
unSubscribe.current();
82+
83+
init();
84+
85+
unSubscribe.current = props.diffFile.subscribe(init);
86+
});
87+
88+
const onOpenAddWidget = (lineNumber: number, side: SplitSide) => {
89+
widget.side = side;
90+
widget.lineNumber = lineNumber;
91+
};
92+
</script>
93+
94+
{#if !hasHidden}
95+
<tr data-line={props.lineNumber} data-state={hasDiff ? 'diff' : 'plain'} class="diff-line">
96+
{#if oldLine.lineNumber}
97+
<td
98+
class="diff-line-old-num group relative w-[1%] min-w-[40px] select-none pl-[10px] pr-[10px] text-right align-top"
99+
style={`
100+
background-color: ${getLineNumberBG(false, oldLineIsDelete(), hasDiff)},
101+
color: var(${hasDiff ? plainLineNumberColorName : expandLineNumberColorName})
102+
`}
103+
>
104+
{#if hasDiff && enableAddWidget}
105+
<DiffSplitAddWidget
106+
index={props.index}
107+
lineNumber={oldLine?.lineNumber || 0}
108+
side={SplitSide.old}
109+
diffFile={props.diffFile}
110+
onWidgetClick={onAddWidgetClick}
111+
className="absolute left-[100%] z-[1] translate-x-[-50%]"
112+
{onOpenAddWidget}
113+
/>
114+
{/if}
115+
<span
116+
data-line-num={oldLine?.lineNumber}
117+
style={` opacity: ${hasChange ? undefined : 0.5} `}
118+
>
119+
{oldLine?.lineNumber}
120+
</span>
121+
</td>
122+
<td
123+
class="diff-line-old-content group relative pr-[10px] align-top"
124+
style={` background-color: ${getContentBG(false, oldLineIsDelete(), hasDiff)} `}
125+
data-side={SplitSide[SplitSide.old]}
126+
>
127+
{#if hasDiff && enableAddWidget}
128+
<DiffSplitAddWidget
129+
index={props.index}
130+
lineNumber={oldLine?.lineNumber || 0}
131+
side={SplitSide.old}
132+
diffFile={props.diffFile}
133+
onWidgetClick={onAddWidgetClick}
134+
className="absolute right-[100%] z-[1] translate-x-[50%]"
135+
{onOpenAddWidget}
136+
/>
137+
{/if}
138+
<DiffContent
139+
enableWrap={true}
140+
diffFile={props.diffFile}
141+
rawLine={oldLine?.value || ''}
142+
diffLine={oldLine?.diff}
143+
plainLine={oldPlainLine}
144+
syntaxLine={oldSyntaxLine}
145+
enableHighlight={!!enableHighlight}
146+
/>
147+
</td>
148+
{:else}
149+
<td
150+
class="diff-line-old-placeholder select-none"
151+
style={`background-color': var(${emptyBGName}) `}
152+
colspan={2}
153+
>
154+
<span>&ensp;</span>
155+
</td>
156+
{/if}
157+
{#if newLine.lineNumber}
158+
<td
159+
class="diff-line-new-num group relative w-[1%] min-w-[40px] select-none border-l-[1px] pl-[10px] pr-[10px] text-right align-top"
160+
style={`
161+
background-color: ${getLineNumberBG(newLineIsAdded(), false, hasDiff)},
162+
color: var(${hasDiff ? plainLineNumberColorName : expandLineNumberColorName}),
163+
border-left-color: var(${borderColorName}),
164+
border-left-style: solid
165+
`}
166+
>
167+
{#if hasDiff && enableAddWidget}
168+
<DiffSplitAddWidget
169+
index={props.index}
170+
lineNumber={newLine?.lineNumber || 0}
171+
side={SplitSide.new}
172+
diffFile={props.diffFile}
173+
onWidgetClick={onAddWidgetClick}
174+
className="absolute left-[100%] z-[1] translate-x-[-50%]"
175+
{onOpenAddWidget}
176+
/>
177+
{/if}
178+
<span
179+
data-line-num={newLine?.lineNumber}
180+
style={` opacity: ${hasChange ? undefined : 0.5} `}
181+
>
182+
{newLine?.lineNumber}
183+
</span>
184+
</td>
185+
<td
186+
class="diff-line-new-content group relative pr-[10px] align-top"
187+
style={`background-color: ${getContentBG(newLineIsAdded(), false, hasDiff)} `}
188+
data-side={SplitSide[SplitSide.new]}
189+
>
190+
{#if hasDiff && enableAddWidget}
191+
<DiffSplitAddWidget
192+
index={props.index}
193+
lineNumber={newLine?.lineNumber || 0}
194+
side={SplitSide.new}
195+
diffFile={props.diffFile}
196+
onWidgetClick={onAddWidgetClick}
197+
className="absolute right-[100%] z-[1] translate-x-[50%]"
198+
{onOpenAddWidget}
199+
/>
200+
{/if}
201+
<DiffContent
202+
enableWrap={true}
203+
diffFile={props.diffFile}
204+
rawLine={newLine?.value || ''}
205+
diffLine={newLine?.diff}
206+
plainLine={newPlainLine}
207+
syntaxLine={newSyntaxLine}
208+
enableHighlight={!!enableHighlight}
209+
/>
210+
</td>
211+
{:else}
212+
<td
213+
class="diff-line-new-placeholder select-none border-l-[1px]"
214+
style={`
215+
background-color: var(${emptyBGName}),
216+
border-left-color: var(${borderColorName}),
217+
border-left-style: solid
218+
`}
219+
colspan={2}
220+
>
221+
<span>&ensp;</span>
222+
</td>
223+
{/if}
224+
</tr>
225+
{/if}

0 commit comments

Comments
 (0)