mirror of
https://seed.radicle.dev/rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5.git
synced 2026-11-02 02:00:31 +08:00
Add link to code line numbers
Signed-off-by: Sebastian Martinez <sebastinez@me.com>
This commit is contained in:
@@ -1,12 +1,20 @@
|
||||
<script lang="ts">
|
||||
import type { Blob } from "@app/project";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
export let blob: Blob;
|
||||
export let line: number | null;
|
||||
|
||||
const lastCommit = blob.info.lastCommit;
|
||||
const lines = blob.binary ? 0 : (blob.content.match(/\n/g) || []).length;
|
||||
const lineNumbers = Array(lines).fill(0).map((_, index) => (index + 1).toString());
|
||||
const parentDir = blob.path.match(/^.*\/|/)?.values().next().value;
|
||||
|
||||
// Waiting onMount, due to the line numbers still loading.
|
||||
onMount(() => {
|
||||
const lineElement = document.getElementById(`L${line}`);
|
||||
if (lineElement) lineElement.scrollIntoView();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@@ -55,6 +63,12 @@
|
||||
user-select: none;
|
||||
padding: 0 1rem 0.5rem 1rem;
|
||||
}
|
||||
.line-number {
|
||||
display: block;
|
||||
}
|
||||
.line-number:hover {
|
||||
color: var(--color-foreground);
|
||||
}
|
||||
|
||||
.code {
|
||||
padding-bottom: 0.5rem;
|
||||
@@ -118,7 +132,9 @@
|
||||
</div>
|
||||
{:else}
|
||||
<pre class="line-numbers">
|
||||
{@html lineNumbers.join("\n")}
|
||||
{#each lineNumbers as lineNumber}
|
||||
<a href="#L{lineNumber}" class="line-number" id="L{lineNumber}">{lineNumber}</a>
|
||||
{/each}
|
||||
</pre>
|
||||
<pre
|
||||
class="code no-scrollbar">
|
||||
|
||||
@@ -173,7 +173,7 @@
|
||||
{#if utils.isMarkdownPath(blob.path)}
|
||||
<Readme content={blob.content} />
|
||||
{:else}
|
||||
<Blob {blob} />
|
||||
<Blob line={browser.line} {blob} />
|
||||
{/if}
|
||||
{:catch}
|
||||
<div class="error error-message file-not-found">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import type { Writable } from 'svelte/store';
|
||||
import type { Config } from "@app/config";
|
||||
import { formatLocationHash } from '@app/utils';
|
||||
import * as proj from '@app/project';
|
||||
|
||||
import Project from './Project.svelte';
|
||||
@@ -12,8 +13,10 @@
|
||||
export let content: proj.ProjectContent = proj.ProjectContent.Tree;
|
||||
export let project: proj.Project;
|
||||
export let config: Config;
|
||||
export let hash: string | null = null;
|
||||
|
||||
const browse: proj.BrowseTo = { content, peer, path: "/" };
|
||||
const line = formatLocationHash(hash);
|
||||
const browse: proj.BrowseTo = { content, peer, path: "/", line };
|
||||
const head = project.branches[project.defaultBranch];
|
||||
|
||||
// route is passed when the URL has more params after e.g. /tree or /history
|
||||
|
||||
@@ -50,22 +50,22 @@
|
||||
<Route path="/tree">
|
||||
<ProjectRoute content={ProjectContent.Tree} {peer} {project} {config} />
|
||||
</Route>
|
||||
<Route path="/tree/*" let:params>
|
||||
<ProjectRoute route={params["*"]} content={ProjectContent.Tree} {peer} {project} {config} />
|
||||
<Route path="/tree/*" let:params let:location>
|
||||
<ProjectRoute route={params["*"]} hash={location.hash} content={ProjectContent.Tree} {peer} {project} {config} />
|
||||
</Route>
|
||||
|
||||
<Route path="/history">
|
||||
<ProjectRoute content={ProjectContent.History} {peer} {project} {config} />
|
||||
</Route>
|
||||
<Route path="/history/*" let:params>
|
||||
<ProjectRoute route={params["*"]} content={ProjectContent.History} {peer} {project} {config} />
|
||||
<Route path="/history/*" let:params let:location>
|
||||
<ProjectRoute route={params["*"]} hash={location.hash} content={ProjectContent.History} {peer} {project} {config} />
|
||||
</Route>
|
||||
|
||||
<Route path="/commits/:commit" let:params>
|
||||
<ProjectRoute revision={params.commit} content={ProjectContent.Commit} {peer} {project} {config} />
|
||||
</Route>
|
||||
<Route path="/commits/*" let:params>
|
||||
<ProjectRoute route={params["*"]} content={ProjectContent.Commit} {peer} {project} {config} />
|
||||
<Route path="/commits/*" let:params let:location>
|
||||
<ProjectRoute route={params["*"]} hash={location.hash} content={ProjectContent.Commit} {peer} {project} {config} />
|
||||
</Route>
|
||||
</Router>
|
||||
{:catch}
|
||||
|
||||
@@ -97,6 +97,7 @@ export interface Browser {
|
||||
revision: string | null;
|
||||
peer: string | null;
|
||||
path: string | null;
|
||||
line: number | null;
|
||||
}
|
||||
|
||||
export const browserStore = writable({
|
||||
@@ -105,6 +106,7 @@ export const browserStore = writable({
|
||||
revision: null,
|
||||
peer: null,
|
||||
path: null,
|
||||
line: null,
|
||||
} as Browser);
|
||||
|
||||
export interface BrowseTo {
|
||||
@@ -112,6 +114,7 @@ export interface BrowseTo {
|
||||
revision?: string | null;
|
||||
path?: string | null;
|
||||
peer?: string | null;
|
||||
line?: number | null;
|
||||
}
|
||||
|
||||
export interface PathOptions extends BrowseTo {
|
||||
|
||||
@@ -86,6 +86,11 @@ export function formatSeedAddress(id: string, host: string, port: number): strin
|
||||
return `${id}@${host}:${port}`;
|
||||
}
|
||||
|
||||
export function formatLocationHash(hash: string | null): number | null {
|
||||
if (hash && hash.match(/^#L[0-9]+$/)) return parseInt(hash.slice(2));
|
||||
return null;
|
||||
}
|
||||
|
||||
export function formatSeedId(id: string): string {
|
||||
return id.substring(0, 6)
|
||||
+ '…'
|
||||
|
||||
Reference in New Issue
Block a user