<script lang="ts">
import Nav from '../../Nav.svelte';
import Atom from './Atom.svelte';
import Pos from './Pos.svelte';
import Edge from './Edge.svelte';
import Contents from './Contents.svelte';
import Meta from './Meta.svelte';
import type { Deps, Hunk } from './Types';
export let data: {
deps: Deps;
authors: { login?: string; key: string }[];
hash: string;
repo: string;
owner: string;
header: {
message: string;
timestamp: string;
description: string | null;
};
hunks: Hunk[];
};
let date = new Intl.DateTimeFormat('en-US', {
dateStyle: 'medium',
timeStyle: 'short'
}).format(new Date(data.header.timestamp));
</script>
<svelte:head>
<title>{data.owner} / {data.repo} - {data.hash}</title>
</svelte:head>
<div class="p-3">
<Nav user={data.owner} repo={data.repo} link={true} />
<h1 class="mt-5">{data.header.message}</h1>
<div class="flex items-center py-3 gap-5">
{#if data.authors?.length}
{#if data.authors[0]?.login}
<img
class="profile-picture"
src="/identicon/{data.authors[0].login}"
alt="Profile picture of {data.authors[0].login}" />
{:else}
<img alt="" class="profile-picture" src="/identicon/question/small" />
{/if}
{:else}
<img class="profile-picture" src="/identicon/question/small" alt="unknown author" />
{/if}
<div class="flex flex-col">
<div>
{#each data.authors as a, i}{#if i > 0},
{/if}{#if a.login}<a class="link" href="/{a.login}">{a.login}</a>{:else}
<span class="font-mono">{a.key}</span>
{/if}{/each}
</div>
<div>
{date}
</div>
<div>
<code class="hash">{data.hash}</code>
</div>
</div>
</div>
<h2 class="mt-8">Dependencies</h2>
<ul class="list my-3">
{#if data.deps?.hashes?.length}
{#each data.deps.hashes.slice(2) as d, i}
{#if i >= data.deps?.deps.length + (data.deps?.known?.length || 0)}<li class="list-row">
[*] <a class="link" href={d}><code class="hash">{d}</code></a>
</li>
{:else}
<li>[{i + 2}] <a class="link" href={d}><code class="hash">{d}</code></a></li>
{/if}
{/each}
{/if}
</ul>
<h2 class="mt-8">Change contents</h2>
<ul class="py-3">
{#if data.hunks}
{#each data.hunks as l}
<li class="">
{#if l.FileAdd}
<h3>File addition: <Meta m={l.FileAdd.meta} /></h3>
<div class="context">
<div class="change-newvertex-up">
{#each l.FileAdd.context as cc}<Pos deps={data.deps} c={cc} />{/each}
</div>
</div>
<div class="p-3">
<Contents contents={l.FileAdd.contents} />
</div>
{:else if l.FileMove}
<h6>
File move:{#each l.FileMove.old as m}
<Meta {m} />{/each} → <Meta m={l.FileMove.meta} />
</h6>
<div class="px-3">
<div class="context">
<div class="change-newvertex-up">
{#each l.FileMove.up as cc}<Pos deps={data.deps} c={cc} />{/each}
</div>
</div>
<div class="context">
<div class="change-newvertex-down">
{#each l.FileMove.down as cc}<Pos deps={data.deps} c={cc} />{/each}
</div>
</div>
</div>
{:else if l.FileDel}
<h6>
File deletion:{#each l.FileDel.deleted_names as m}
<Meta {m} />{/each}
</h6>
<div class="px-3">
<Atom deps={data.deps} atom={l.FileDel.del} />
{#if l.FileDel.content_edges.length}
<div class="context">
{#each l.FileDel.content_edges as e, n}{#if n > 0},
{/if}<Edge edge={e} deps={data.deps} />{/each}
</div>
{/if}
</div>
<div class="p-3">
<Contents contents={l.FileDel.content} />
</div>
{:else if l.FileUndel}
<h6>
File un-deletion:{#each l.FileUndel.undel_names as m}
<Meta {m} />{/each}
</h6>
<div class="px-3">
<Atom deps={data.deps} atom={l.FileUndel.undel} />
<div class="context">
{#each l.FileUndel.content_edges as e, n}{#if n > 0},
{/if}<Edge edge={e} deps={data.deps} />{/each}
</div>
</div>
<div class="p-3">
<Contents contents={l.FileUndel.content} />
</div>
{:else if l.SolveNameConflict}
<h6>
Solving a name conflict:{#each l.SolveNameConflict.old as m}
<Meta {m} />{/each}
</h6>
<div class="px-3">
<Atom deps={data.deps} atom={l.SolveNameConflict.name} />
</div>
{:else if l.UnsolveNameConflict}
<h6>
Unsolving a name conflict:{#each l.UnsolveNameConflict.old as m}
<Meta {m} />{/each}
</h6>
<div class="px-3">
<Atom deps={data.deps} atom={l.UnsolveNameConflict.name} />
</div>
{:else if l.Edit}
<h6>Edit in {l.Edit.path} at line {l.Edit.line}</h6>
<div class="px-3">
<Atom deps={data.deps} atom={l.Edit.atom} />
</div>
<div class="px-3 pb-0">
<Contents contents={l.Edit.contents} />
</div>
{:else if l.Replacement}
<h6>Replacement in {l.Replacement.path} at line {l.Replacement.line}</h6>
<div class="px-3">
<Atom deps={data.deps} atom={{ EdgeMap: l.Replacement.del }} />
<Contents contents={l.Replacement.del_contents} />
</div>
<div class="px-3 py-2 m-0">
<Atom deps={data.deps} atom={{ NewVertex: l.Replacement.ins }} />
<Contents contents={l.Replacement.ins_contents} />
</div>
{:else if l.SolveOrderConflict}
<h6>
Solving an order conflict in {l.SolveOrderConflict.path} at line {l.SolveOrderConflict
.line}
</h6>
<div class="px-3">
<Atom deps={data.deps} atom={l.SolveOrderConflict.atom} />
</div>
<div class="p-3 pb-0">
<Contents contents={l.SolveOrderConflict.contents} />
</div>
{:else if l.UnsolveOrderConflict}
<h6>
Unsolving an order conflict in {l.UnsolveOrderConflict.path} at line {l
.UnsolveOrderConflict.line}
</h6>
<div class="px-3">
<Atom deps={data.deps} atom={l.UnsolveOrderConflict.atom} />
</div>
<div class="p-3 pb-0">
<Contents contents={l.UnsolveOrderConflict.contents} />
</div>
{:else if l.ResurrectZombie}
<h6>
Resurrecting zombies in {l.ResurrectZombie.path} at line {l.ResurrectZombie.line}
</h6>
<div class="px-3">
<Atom deps={data.deps} atom={l.ResurrectZombie.atom} />
</div>
<div class="p-3 pb-0">
<Contents contents={l.ResurrectZombie.contents} />
</div>
{:else if l.AddRoot}
<h6>Add root</h6>
<div class="px-3">
<Atom deps={data.deps} atom={l.AddRoot.name} />
<Atom deps={data.deps} atom={l.AddRoot.atom} />
</div>
{:else if l.DelRoot}
<h6>Del root</h6>
<div class="px-3">
<Atom deps={data.deps} atom={l.DelRoot.name} />
<Atom deps={data.deps} atom={l.DelRoot.atom} />
</div>
{/if}
</li>
{/each}
{:else}
This change cannot be displayed, possibly because it contains binary files.
{/if}
</ul>
</div>
<style global>
img.profile-picture {
width: 50px;
height: 50px;
border-radius: 50%;
padding: 0;
background-color: white;
}
:global {
.hash {
color: var(--color-neutral-500);
}
.change-context,
.permissions {
font-size: 90%;
}
.change-newvertex-up::before {
content: '↑';
}
.change-newvertex-down::before {
content: '↓';
}
div.change_addition::before {
content: '+';
}
div.change_deletion::before {
content: '-';
}
div.change_addition::before,
div.change_deletion::before {
position: relative;
margin: -5px;
display: inline-block;
padding: 5px 15px 5px 5px;
}
pre.change_deletion,
pre.change_addition {
overflow: inherit;
}
.change_deletion code,
.change_addition code {
padding: 4px 5px !important;
margin: -4px 0 !important;
display: inline-block !important;
}
.change_deletion code {
color: #721c24;
background-color: #f8d7da;
}
.change_addition code {
color: #155724;
background-color: #d4edda;
}
.change-context div {
display: inline-block;
}
.change-context div.context:first-child::before {
content: '';
}
.change-context div.context::before {
content: ', ';
}
}
</style>