Files
horse/zenno/src/routes/doc/Article.svelte
T
2026-06-05 15:13:11 -04:00

65 lines
1.3 KiB
Svelte

<script lang="ts">
import { type Snippet } from 'svelte';
import Sec from './Sec.svelte';
import { sections, type Section } from './article.svelte';
interface Props {
head: Snippet;
children: Snippet;
}
let { head, children }: Props = $props();
let tocViewed = $state(false);
let tocElem: HTMLElement | undefined = $state();
const observeTOC: IntersectionObserverCallback = (entries, obs) => {
for (const e of entries) {
if (!e.isIntersecting) {
continue;
}
tocViewed = true;
obs.disconnect();
}
};
$effect(() => {
if (tocElem == null) {
return;
}
const obs = new IntersectionObserver(observeTOC, { rootMargin: '20% 0px' });
obs.observe(tocElem);
});
function tocClass(s: Section) {
switch (s.h) {
case 1:
return null;
case 2:
return null;
case 3:
return 'ml-4';
case 4:
return 'ml-8';
case 5:
return 'ml-12';
case 6:
return 'ml-16';
}
}
</script>
<article class="mx-auto max-w-4xl text-justify hyphens-auto">
{@render head()}
{#if sections.length > 0}
<Sec h={2} id="toc" toc={false}>Table of Contents</Sec>
<ul class="mb-4 list-disc pl-4" bind:this={tocElem}>
{#if tocViewed}
{#each sections as s (s.id)}
<li class={tocClass(s)}><a href={`#${s.id}`}>{@render s.children()}</a></li>
{/each}
{/if}
</ul>
{/if}
{@render children()}
</article>