blob: 131d2e3a33c515ab7cd062575e949660c03153a8 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
<script lang="ts">
import { diffLines } from 'diff';
interface Props {
before: string;
after: string;
beforeLabel?: string;
afterLabel?: string;
maxHeight?: number;
}
let { before, after, beforeLabel = '原版本', afterLabel = '新版本', maxHeight = 480 }: Props = $props();
const parts = $derived(diffLines(before ?? '', after ?? ''));
const lines = $derived.by(() => {
const out: { t: 'a' | 'd' | 'c'; text: string }[] = [];
for (const p of parts) {
const pieces = p.value.replace(/\n$/, '').split('\n');
for (const piece of pieces) {
if (p.added) out.push({ t: 'a', text: piece });
else if (p.removed) out.push({ t: 'd', text: piece });
else out.push({ t: 'c', text: piece });
}
}
return out;
});
</script>
<div>
<div class="text-muted-foreground text-sm mb-1 flex gap-4">
<span><i class="inline-block size-2.5 rounded-sm mr-1 bg-emerald-200" aria-hidden="true"></i>新增({afterLabel})</span>
<span><i class="inline-block size-2.5 rounded-sm mr-1 bg-red-200" aria-hidden="true"></i>删除({beforeLabel})</span>
</div>
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
<div class="overflow-auto bg-card border border-border rounded-md py-2 px-3" style:max-height="{maxHeight}px" tabindex="0" aria-label="代码差异" role="region">
{#each lines as l, i (i)}
{#if l.t === 'a'}
<span class="select-none" aria-hidden="true"></span><span class="font-mono text-xs inline-block w-full whitespace-pre-wrap break-all bg-emerald-50 text-emerald-900">+{l.text}</span>
{:else if l.t === 'd'}
<span class="select-none" aria-hidden="true"></span><span class="font-mono text-xs inline-block w-full whitespace-pre-wrap break-all bg-red-50 text-red-900">−{l.text}</span>
{:else}
<span class="select-none" aria-hidden="true"> </span><span class="font-mono text-xs inline-block w-full whitespace-pre-wrap break-all">{l.text}</span>
{/if}
{/each}
</div>
</div>
|