Browse Source

open #199 some extra data

master
Nuša Pukšič 12 months ago
parent
commit
7327d28c54
  1. 124
      src/lib/components/util/TocToggle.svelte
  2. 30
      src/lib/parser.ts

124
src/lib/components/util/TocToggle.svelte

@ -0,0 +1,124 @@
<script lang="ts">
import {
Button,
Sidebar,
SidebarGroup,
SidebarItem,
SidebarWrapper,
Skeleton,
TextPlaceholder,
Tooltip,
} from "flowbite-svelte";
import { onMount } from "svelte";
import { BookOutline } from "flowbite-svelte-icons";
import { pharosInstance } from "$lib/parser";
import { page } from "$app/state";
let { rootId } = $props<{ rootId: string }>();
if (rootId !== $pharosInstance.getRootIndexId()) {
console.error("Root ID does not match parser root index ID");
}
const tocBreakpoint = 1140;
let activeHash = $state(page.url.hash);
let showToc: boolean = $state(true);
let showTocButton: boolean = $state(false);
function normalizeHashPath(str: string): string {
return str
.toLowerCase()
.replace(/\s+/g, "-")
.replace(/[^\w-]/g, "");
}
function scrollToElementWithOffset() {
const hash = window.location.hash;
if (hash) {
const targetElement = document.querySelector(hash);
if (targetElement) {
const headerOffset = 80;
const elementPosition = targetElement.getBoundingClientRect().top;
const offsetPosition = elementPosition + window.scrollY - headerOffset;
window.scrollTo({
top: offsetPosition,
behavior: "auto",
});
}
}
}
/**
* Hides the table of contents sidebar when the window shrinks below a certain size. This
* prevents the sidebar from occluding the article content.
*/
function setTocVisibilityOnResize() {
showToc = window.innerWidth >= tocBreakpoint;
showTocButton = window.innerWidth < tocBreakpoint;
}
/**
* Hides the table of contents sidebar when the user clicks outside of it.
*/
function hideTocOnClick(ev: MouseEvent) {
const target = ev.target as HTMLElement;
if (target.closest(".sidebar-leather") || target.closest(".btn-leather")) {
return;
}
if (showToc) {
showToc = false;
}
}
onMount(() => {
// Always check whether the TOC sidebar should be visible.
setTocVisibilityOnResize();
window.addEventListener("hashchange", scrollToElementWithOffset);
// Also handle the case where the user lands on the page with a hash in the URL
scrollToElementWithOffset();
window.addEventListener("resize", setTocVisibilityOnResize);
window.addEventListener("click", hideTocOnClick);
return () => {
window.removeEventListener("hashchange", scrollToElementWithOffset);
window.removeEventListener("resize", setTocVisibilityOnResize);
window.removeEventListener("click", hideTocOnClick);
};
});
</script>
{#if showTocButton && !showToc}
<Button
class="btn-leather h-6 !w-auto"
outline={true}
on:click={(ev) => {
showToc = true;
ev.stopPropagation();
}}
>
<BookOutline class="!fill-none mr-1"/>
Table of Contents
</Button>
{/if}
<!-- TODO: Get TOC from parser. -->
<!-- {#if showToc}
<Sidebar class='sidebar-leather fixed top-20 left-0 px-4 w-60' {activeHash}>
<SidebarWrapper>
<SidebarGroup class='sidebar-group-leather overflow-y-scroll'>
{#each events as event}
<SidebarItem
class='sidebar-item-leather'
label={event.getMatchingTags('title')[0][1]}
href={`${$page.url.pathname}#${normalizeHashPath(event.getMatchingTags('title')[0][1])}`}
/>
{/each}
</SidebarGroup>
</SidebarWrapper>
</Sidebar>
{/if} -->

30
src/lib/parser.ts

@ -121,6 +121,11 @@ export default class Pharos {
*/ */
private eventsByLevelMap: Map<number, string[]> = new Map<number, string[]>(); private eventsByLevelMap: Map<number, string[]> = new Map<number, string[]>();
/**
* A map of blog entries
*/
private blogEntries: Map<string, NDKEvent> = new Map<string, NDKEvent>();
/** /**
* When `true`, `getEvents()` should regenerate the event tree to propagate updates. * When `true`, `getEvents()` should regenerate the event tree to propagate updates.
*/ */
@ -177,6 +182,14 @@ export default class Pharos {
this.parse(content); this.parse(content);
} }
getBlogEntries() {
return this.blogEntries;
}
getIndexMetadata(): IndexMetadata {
return this.rootIndexMetadata;
}
/** /**
* Generates and stores Nostr events from the parsed AsciiDoc document. The events can be * Generates and stores Nostr events from the parsed AsciiDoc document. The events can be
* modified via the parser's API and retrieved via the `getEvents()` method. * modified via the parser's API and retrieved via the `getEvents()` method.
@ -617,6 +630,23 @@ export default class Pharos {
tags.map(tag => this.ndk.fetchEventFromTag(tag, event)) tags.map(tag => this.ndk.fetchEventFromTag(tag, event))
); );
// if a blog, save complete events for later
if (event.getMatchingTags("type")[0][1] === 'blog') {
childEvents.forEach(child => {
if (child) {
this.blogEntries.set(child?.getMatchingTags("d")?.[0]?.[1], child);
}
})
}
// populate metadata
if (event.created_at) {
this.rootIndexMetadata.publicationDate = new Date(event.created_at * 1000).toDateString();
}
if (event.getMatchingTags('image')) {
this.rootIndexMetadata.coverImage = event.getMatchingTags('image')[0][1];
}
// Michael J - 15 December 2024 - This could be further parallelized by recursively fetching // Michael J - 15 December 2024 - This could be further parallelized by recursively fetching
// children of index events before processing them for content. We won't make that change now, // children of index events before processing them for content. We won't make that change now,
// as it would increase complexity, but if performance suffers, we can revisit this option. // as it would increase complexity, but if performance suffers, we can revisit this option.

Loading…
Cancel
Save