mirror of
https://github.com/hcengineering/platform.git
synced 2025-05-14 11:24:06 +00:00
229 lines
6.3 KiB
Svelte
229 lines
6.3 KiB
Svelte
<!--
|
|
// Copyright © 2023 Hardcore Engineering Inc.
|
|
//
|
|
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License. You may
|
|
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
//
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
-->
|
|
<script lang="ts">
|
|
import { Html, Loading, themeStore } from '@hcengineering/ui'
|
|
import { DiffFile, DiffLine, DiffLineType, DiffViewMode } from '@hcengineering/diffview'
|
|
|
|
import { DiffLineRenderResult, RenderOptions, renderHunk } from '../render'
|
|
|
|
export let file: DiffFile
|
|
export let mode: DiffViewMode
|
|
export let tabSize = 4
|
|
|
|
const options: RenderOptions = {
|
|
syntaxHighlight: {
|
|
language: file.language ?? ''
|
|
}
|
|
}
|
|
|
|
function codeLineClass (line: DiffLine): string {
|
|
return `line-${line.type}`
|
|
}
|
|
|
|
$: highlighted = file.hunks.map((hunk) => renderHunk(hunk, options))
|
|
|
|
function prepareLinesForUnifiedView (lines: DiffLineRenderResult[]): DiffLine[] {
|
|
return lines.map(({ before, after }) => (after.type !== DiffLineType.EMPTY ? after : before))
|
|
}
|
|
|
|
function prepareLinesForSplitView (lines: DiffLineRenderResult[]): DiffLineRenderResult[] {
|
|
const before: DiffLine[] = []
|
|
const after: DiffLine[] = []
|
|
|
|
let moved: DiffLine[] = []
|
|
|
|
for (const line of lines) {
|
|
before.push(line.before)
|
|
if (line.after.type === 'insert') {
|
|
after.push(line.after)
|
|
} else if (line.after.type === 'context') {
|
|
after.push(...moved)
|
|
moved = []
|
|
after.push(line.after)
|
|
} else {
|
|
moved.push(line.after)
|
|
}
|
|
}
|
|
after.push(...moved)
|
|
|
|
const result: DiffLineRenderResult[] = []
|
|
while (before.length > 0 && after.length > 0) {
|
|
const beforeLine = before.shift()
|
|
const afterLine = after.shift()
|
|
if (beforeLine && afterLine) {
|
|
result.push({ before: beforeLine, after: afterLine })
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
</script>
|
|
|
|
<div
|
|
class="highlight-container"
|
|
class:highlight-container-dark={$themeStore.dark}
|
|
class:highlight-container-light={!$themeStore.dark}
|
|
>
|
|
{#if highlighted === undefined}
|
|
<Loading />
|
|
{:else}
|
|
<table class="diff-table diff-table-{mode} tab-size" data-tab-size={tabSize}>
|
|
<colgroup>
|
|
{#if mode === 'unified'}
|
|
<col class="num-col" />
|
|
<col class="num-col" />
|
|
<col class="code-col" />
|
|
{:else}
|
|
<col class="num-col" />
|
|
<col class="code-col" />
|
|
<col class="num-col" />
|
|
<col class="code-col" />
|
|
{/if}
|
|
</colgroup>
|
|
<tbody>
|
|
{#each highlighted as hhunk}
|
|
{@const hunk = hhunk.hunk}
|
|
|
|
{#if mode === 'unified'}
|
|
{@const lines = prepareLinesForUnifiedView(hhunk.lines)}
|
|
|
|
<tr>
|
|
<td class="num-line line-header" />
|
|
<td class="num-line line-header" />
|
|
<td class="code-line line-header">{hunk.header}</td>
|
|
</tr>
|
|
{#each lines as line}
|
|
{@const lineClass = codeLineClass(line)}
|
|
<tr>
|
|
<td class="num-line {lineClass}">{line.oldNumber ?? ''}</td>
|
|
<td class="num-line {lineClass}">{line.newNumber ?? ''}</td>
|
|
<td class="code-line select-text {lineClass}" data-code-marker={line.prefix}>
|
|
<Html value={line.content} />
|
|
</td>
|
|
</tr>
|
|
{/each}
|
|
{:else}
|
|
{@const lines = prepareLinesForSplitView(hhunk.lines)}
|
|
|
|
<tr>
|
|
<td class="num-line line-header" />
|
|
<td class="code-line line-header" colspan="3">{hunk.header}</td>
|
|
</tr>
|
|
{#each lines as line}
|
|
{@const before = line.before}
|
|
{@const after = line.after}
|
|
|
|
{@const beforeLineClass = codeLineClass(before)}
|
|
{@const afterLineClass = codeLineClass(after)}
|
|
<tr>
|
|
<td class="num-line {beforeLineClass}">{before.oldNumber ?? ''}</td>
|
|
<td class="code-line select-text {beforeLineClass}" data-code-marker={before.prefix}>
|
|
<Html value={before.content} />
|
|
</td>
|
|
<td class="num-line {afterLineClass}">{after.newNumber ?? ''}</td>
|
|
<td class="code-line select-text {afterLineClass}" data-code-marker={after.prefix}>
|
|
<Html value={after.content} />
|
|
</td>
|
|
</tr>
|
|
{/each}
|
|
{/if}
|
|
{/each}
|
|
</tbody>
|
|
</table>
|
|
{/if}
|
|
</div>
|
|
|
|
<style lang="scss">
|
|
.highlight-container-light :global {
|
|
@import './theme/github.scss';
|
|
}
|
|
|
|
.highlight-container-dark :global {
|
|
@import './theme/github-dark.scss';
|
|
}
|
|
|
|
.diff-table {
|
|
font-family: var(--mono-font);
|
|
font-size: 0.8125rem;
|
|
width: 100%;
|
|
|
|
&.tab-size {
|
|
tab-size: attr(data-tab-size);
|
|
}
|
|
|
|
&.diff-table-split {
|
|
table-layout: fixed;
|
|
}
|
|
}
|
|
|
|
.diff-table-split .code-line + .num-line {
|
|
border-left: 1px solid var(--theme-divider-color);
|
|
}
|
|
|
|
td {
|
|
&.code-line {
|
|
border-left: 1px solid var(--theme-divider-color);
|
|
}
|
|
|
|
&.line-header {
|
|
background-color: var(--theme-diffview-block-header-color);
|
|
padding-top: 0.25rem;
|
|
padding-bottom: 0.25rem;
|
|
white-space: pre-wrap;
|
|
}
|
|
|
|
&.line-insert {
|
|
background-color: var(--theme-diffview-insert-line-color);
|
|
}
|
|
|
|
&.line-delete {
|
|
background-color: var(--theme-diffview-delete-line-color);
|
|
}
|
|
|
|
&.line-empty {
|
|
background-color: var(--theme-diffview-empty-line-color);
|
|
}
|
|
}
|
|
|
|
.num-col {
|
|
width: 1px;
|
|
min-width: 3.5rem;
|
|
}
|
|
|
|
.num-line {
|
|
padding: 0 0.5rem;
|
|
text-align: right;
|
|
vertical-align: top;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
position: relative;
|
|
}
|
|
|
|
.code-line {
|
|
position: relative;
|
|
color: var(--theme-diffview-line-color);
|
|
padding: 0 1.5rem;
|
|
vertical-align: top;
|
|
white-space: pre-wrap;
|
|
word-wrap: anywhere;
|
|
}
|
|
|
|
.code-line::before {
|
|
content: attr(data-code-marker);
|
|
position: absolute;
|
|
left: 0.5rem;
|
|
}
|
|
</style>
|