Browse Source

First pass at ToC layout

master
buttercat1791 9 months ago
parent
commit
608ce2b8e4
  1. 9
      src/lib/components/publications/Publication.svelte
  2. 65
      src/lib/components/publications/TableOfContents.svelte
  3. 7
      src/routes/publication/+page.svelte

9
src/lib/components/publications/Publication.svelte

@ -19,9 +19,9 @@ @@ -19,9 +19,9 @@
import { publicationColumnVisibility } from "$lib/stores";
import BlogHeader from "$components/cards/BlogHeader.svelte";
import Interactions from "$components/util/Interactions.svelte";
import TocToggle from "$components/util/TocToggle.svelte";
import { pharosInstance } from '$lib/parser';
import type { SveltePublicationTree } from "./svelte_publication_tree.svelte";
import TableOfContents from "./TableOfContents.svelte";
let { rootAddress, publicationType, indexEvent } = $props<{
rootAddress: string;
@ -160,7 +160,12 @@ @@ -160,7 +160,12 @@
<!-- Table of contents -->
{#if publicationType !== "blog" || !isLeaf}
<TocToggle {rootId} />
<TableOfContents
depth={0}
onSectionFocused={(address: string) => {
publicationTree.setBookmark(address);
}}
/>
{/if}
<!-- Default publications -->

65
src/lib/components/publications/TableOfContents.svelte

@ -1,22 +1,63 @@ @@ -1,22 +1,63 @@
<script lang='ts'>
import type { TableOfContents } from '$lib/components/publications/table_of_contents.svelte';
import type { TableOfContents, TocEntry } from '$lib/components/publications/table_of_contents.svelte';
import { getContext } from 'svelte';
import { Card } from 'flowbite-svelte';
import { Accordion, AccordionItem, Card } from 'flowbite-svelte';
import Self from './TableOfContents.svelte';
let { rootAddress } = $props<{ rootAddress: string }>();
let {
depth,
onSectionFocused,
} = $props<{
depth: number;
onSectionFocused?: (address: string) => void;
}>();
let toc = getContext('toc') as TableOfContents;
// TODO: Check root address against ToC root address for correctness.
let entries = $derived(
Array
.from(toc.addressMap.values())
.filter((entry) => entry.depth === depth)
);
// Determine the event kind.
// If index, use the publication tree to build the table of contents.
// If single event, build the table of contents from the rendered HTML.
// Each rendered `<h>` should receive an entry in the ToC.
// Track the currently visible section for highlighting
let currentSection = $state<string | null>(null);
// Handle section visibility changes from the IntersectionObserver
function handleSectionVisibility(address: string, isVisible: boolean) {
if (isVisible) {
currentSection = address;
}
}
// Toggle expansion of a ToC entry
async function toggleExpansion(entry: TocEntry) {
// Update the current section in the ToC
const tocEntry = toc.getEntry(entry.address);
if (tocEntry) {
// Ensure the parent sections are expanded
let parent = tocEntry.parent;
while (parent) {
parent.expanded = true;
parent = parent.parent;
}
}
entry.expanded = !entry.expanded;
if (entry.expanded && !entry.childrenResolved) {
onSectionFocused?.(entry.address);
await entry.resolveChildren();
}
}
</script>
<Card class='flex flex-col space-y-2'>
{#each toc as entry}
<a href={entry.href}>{entry.title}</a>
<Accordion flush class='overflow-y-auto w-64 p-4'>
{#each entries as entry}
<AccordionItem open={entry.expanded}>
<h3 class='text-lg font-bold'>{entry.title}</h3>
{#if entry.children.length > 0}
<Self depth={depth + 1} onSectionFocused={onSectionFocused} />
{/if}
</AccordionItem>
{/each}
</Card>
</Accordion>

7
src/routes/publication/+page.svelte

@ -6,11 +6,18 @@ @@ -6,11 +6,18 @@
import Processor from "asciidoctor";
import ArticleNav from "$components/util/ArticleNav.svelte";
import { SveltePublicationTree } from "$lib/components/publications/svelte_publication_tree.svelte";
import { TableOfContents } from "$lib/components/publications/table_of_contents.svelte";
let { data }: PageProps = $props();
const publicationTree = new SveltePublicationTree(data.indexEvent, data.ndk);
const toc = new TableOfContents(
data.indexEvent.tagAddress(),
publicationTree,
data.url?.pathname ?? "",
);
setContext("publicationTree", publicationTree);
setContext("toc", toc);
setContext("asciidoctor", Processor());
// Get publication metadata for OpenGraph tags

Loading…
Cancel
Save