|
|
|
|
@ -16,25 +16,41 @@
@@ -16,25 +16,41 @@
|
|
|
|
|
return events.filter((event) => event != null); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const converter = new showdown.Converter(); |
|
|
|
|
function normalizeHashPath(str: string): string { |
|
|
|
|
return str |
|
|
|
|
.toLowerCase() |
|
|
|
|
.replace(/\s+/g, '-') |
|
|
|
|
.replace(/[^\w-]/g, ''); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const transitionParams = { |
|
|
|
|
x: -320, |
|
|
|
|
duration: 200, |
|
|
|
|
easing: sineIn |
|
|
|
|
}; |
|
|
|
|
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', |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let width: number; |
|
|
|
|
let breakpoint: number = 768; // Tailwind md breakpoint |
|
|
|
|
let drawerHidden: boolean = false; |
|
|
|
|
$: width >= breakpoint |
|
|
|
|
? drawerHidden = false |
|
|
|
|
: drawerHidden = true; |
|
|
|
|
onMount(() => { |
|
|
|
|
width >= breakpoint |
|
|
|
|
? drawerHidden = false |
|
|
|
|
: drawerHidden = true; |
|
|
|
|
window.addEventListener('hashchange', scrollToElementWithOffset); |
|
|
|
|
// Also handle the case where the user lands on the page with a hash in the URL |
|
|
|
|
scrollToElementWithOffset(); |
|
|
|
|
|
|
|
|
|
return () => { |
|
|
|
|
window.removeEventListener('hashchange', scrollToElementWithOffset); |
|
|
|
|
}; |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
const converter = new showdown.Converter(); |
|
|
|
|
</script> |
|
|
|
|
|
|
|
|
|
{#await getEvents()} |
|
|
|
|
@ -49,12 +65,12 @@
@@ -49,12 +65,12 @@
|
|
|
|
|
<!-- TODO: Handle hash paths for navigation within the article. --> |
|
|
|
|
<Sidebar class='sidebar-leather fixed top-20 left-0 px-4 w-60' {activeHash}> |
|
|
|
|
<SidebarWrapper> |
|
|
|
|
<SidebarGroup> |
|
|
|
|
<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}#${event.getMatchingTags('title')[0][1]}`} |
|
|
|
|
href={`${$page.url.pathname}#${normalizeHashPath(event.getMatchingTags('title')[0][1])}`} |
|
|
|
|
/> |
|
|
|
|
{/each} |
|
|
|
|
</SidebarGroup> |
|
|
|
|
@ -63,7 +79,13 @@
@@ -63,7 +79,13 @@
|
|
|
|
|
<div class='flex flex-col space-y-4 max-w-2xl'> |
|
|
|
|
{#each events as event} |
|
|
|
|
<div class='note-leather flex flex-col space-y-2'> |
|
|
|
|
<Heading tag='h3' class='h-leather'>{event.getMatchingTags('title')[0][1]}</Heading> |
|
|
|
|
<Heading |
|
|
|
|
tag='h3' |
|
|
|
|
class='h-leather' |
|
|
|
|
id={normalizeHashPath(event.getMatchingTags('title')[0][1])} |
|
|
|
|
> |
|
|
|
|
{event.getMatchingTags('title')[0][1]} |
|
|
|
|
</Heading> |
|
|
|
|
{@html converter.makeHtml(event.content)} |
|
|
|
|
</div> |
|
|
|
|
{/each} |
|
|
|
|
@ -71,24 +93,7 @@
@@ -71,24 +93,7 @@
|
|
|
|
|
{/await} |
|
|
|
|
|
|
|
|
|
<style> |
|
|
|
|
.article { |
|
|
|
|
display: flex; |
|
|
|
|
padding: 1rem; |
|
|
|
|
} |
|
|
|
|
.toc { |
|
|
|
|
padding: 3%; |
|
|
|
|
min-width: 5%; |
|
|
|
|
padding-top: 1%; |
|
|
|
|
border: 1px white solid; |
|
|
|
|
border-radius: 10px; |
|
|
|
|
border-top-width: 5px; |
|
|
|
|
} |
|
|
|
|
.article-content { |
|
|
|
|
min-width: 80%; |
|
|
|
|
max-width: 85%; |
|
|
|
|
padding: 1%; |
|
|
|
|
border: 1px white solid; |
|
|
|
|
border-radius: 10px; |
|
|
|
|
border-top-width: 5px; |
|
|
|
|
:global(.sidebar-group-leather) { |
|
|
|
|
max-height: calc(100vh - 8rem); |
|
|
|
|
} |
|
|
|
|
</style> |
|
|
|
|
|