~ knotless Search/
↑↓ move↵ open⇧↵ all results

johnandersen777.bsky.social/knotless

git that lives in your Atmosphere account

Forked from chadtmiller.com/knotless

0
0
52 lines · 2.0 KB Raw History
<script lang="ts">
	import { page } from '$app/state';
	import { goto } from '$app/navigation';
	import { highlight } from '#lib/highlight.ts';
	import { onMount, type Snippet } from 'svelte';
	/** A text file, with a gutter of line numbers to link to, and before it `gutter`, a column as tall as the text, when given. A line's number marks it, shift and a second marks the lines between. */
	let {
		text,
		lines,
		ranges,
		gutter
	}: { text: string; lines: number; ranges?: string | null; gutter?: Snippet } = $props();
	/** The lines `#L5` or `#L5-L9` marks, first to last, or null. */
	const marked = $derived.by(() => {
		const m = /^#L(\d+)(?:-L(\d+))?$/.exec(page.url.hash);
		if (!m) return null;
		const a = +m[1];
		const b = m[2] ? +m[2] : a;
		const first = Math.max(1, Math.min(a, b));
		const last = Math.min(lines, Math.max(a, b));
		return first <= last ? { first, last } : null;
	});
	let ln: HTMLElement | undefined = $state();
	onMount(() => {
		if (marked) ln?.querySelector(`#L${marked.first}`)?.scrollIntoView({ block: 'center' });
	});
	function mark(e: MouseEvent) {
		const a = (e.target as Element).closest('a');
		const n = a ? +a.id.slice(1) : 0;
		if (!n || e.metaKey || e.ctrlKey || e.altKey) return;
		e.preventDefault();
		const hash =
			e.shiftKey && marked ? (n === marked.first ? `#L${n}` : `#L${marked.first}-L${n}`) : `#L${n}`;
		goto(hash, { replace: true, reset: false });
	}
</script>

<div class="code" class:gutted={gutter}>
	{#if marked}<div
			class="marked"
			style:--first={marked.first}
			style:--count={marked.last - marked.first + 1}
		></div>{/if}{#if gutter}{@render gutter()}{/if}<!-- svelte-ignore a11y_click_events_have_key_events, a11y_no_noninteractive_element_interactions -->
	<pre
		class="ln"
		aria-hidden="true"
		bind:this={ln}
		onclick={mark}>{#each { length: lines }, i (i)}<a id="L{i + 1}" href="#L{i + 1}" tabindex="-1"
				>{i + 1}</a
			>{'\n'}{/each}</pre>
	<pre class="src" use:highlight={{ ranges, text }}><code>{text}</code></pre>
</div>