pretty good start on blog page
This commit is contained in:
@@ -1,5 +1,106 @@
|
||||
---
|
||||
import Base from "@layout/Base";
|
||||
|
||||
import { getFormattedDate } from "@utils/date";
|
||||
import { calcReadTime } from '@utils/post'
|
||||
import { authPB } from "@utils/pocketbase";
|
||||
const { slug } = Astro.params
|
||||
export const prerender = false
|
||||
---
|
||||
|
||||
const pb = await authPB()
|
||||
|
||||
const post = await pb.collection('posts').getFirstListItem(`slug="${slug}"`)
|
||||
|
||||
const { title, content, publishDate, description } = post
|
||||
|
||||
const headerImage = pb.files.getURL(post, post.headerImage)
|
||||
|
||||
const wordCount = content.split(' ').length;
|
||||
const readTime = calcReadTime(wordCount);
|
||||
const formattedPublishDate = getFormattedDate(publishDate);
|
||||
|
||||
---
|
||||
|
||||
<Base>
|
||||
<div slot="sidebar" class="text-left">
|
||||
<p class="text-2xl">{title}</p>
|
||||
|
||||
<!-- <img src={headerImage}/> -->
|
||||
|
||||
<p class="italic">{description}</p>
|
||||
|
||||
<time datetime={publishDate}>{formattedPublishDate}</time> |
|
||||
{readTime} min. read |
|
||||
{
|
||||
post.tags.map((tag, i) => (
|
||||
<>
|
||||
<a href={`/posts/tag/${tag}/`}>
|
||||
#{tag}
|
||||
</a>
|
||||
{i < post.tags.length - 1 && ", "}
|
||||
</>
|
||||
))
|
||||
}
|
||||
|
||||
<!-- <h2 class="text-lg mt-4">Table of Contents</h2> -->
|
||||
<!-- <ul id="toc" class="text-md"/> -->
|
||||
|
||||
</div>
|
||||
|
||||
<div slot="content" class="py-12">
|
||||
<Fragment set:html={content} />
|
||||
</div>
|
||||
|
||||
|
||||
</Base>
|
||||
|
||||
<style>
|
||||
img {
|
||||
margin-inline: calc(var(--spacing) * 4);
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
function addLink(tag: Element, depth: number) {
|
||||
let lnk = document.createElement('a')
|
||||
lnk.href=`#${tag.id}`
|
||||
lnk.className = 'mt-2 text-[0.6875rem]'
|
||||
lnk.innerHTML = `<span class="mr-1">${"#".repeat(depth)}</span>${tag.innerHTML}`
|
||||
|
||||
let li = document.createElement('li')
|
||||
li.className = 'line-clamp-1 hover:text-accent'
|
||||
li.appendChild(lnk)
|
||||
|
||||
toc?.appendChild(li)
|
||||
}
|
||||
|
||||
// get all titles in the page
|
||||
const titles = document.querySelectorAll('h1, h2, h3')
|
||||
const toc = document.getElementById('toc') as Element
|
||||
// const toc_cnt = document.getElementById('toc-container') as Element
|
||||
|
||||
// // if there's more than two titles (ie, there's more than just the article title and TOC title, then appropriate to show)
|
||||
// if (titles.length > 2) {
|
||||
// toc_cnt.classList.add('lg:block')
|
||||
// }
|
||||
|
||||
for (let i = 1; i < titles.length; i++) {
|
||||
const t = titles[i] as Element
|
||||
|
||||
// Assign IDs in case they haven't been (by me)
|
||||
t.id = t.innerHTML
|
||||
|
||||
let depth = 1
|
||||
|
||||
// determine what depth to use
|
||||
switch (t.tagName) {
|
||||
case 'H2':
|
||||
depth = 2
|
||||
break
|
||||
case 'H3':
|
||||
depth = 3
|
||||
break
|
||||
}
|
||||
|
||||
addLink(t, depth)
|
||||
}
|
||||
</script>
|
||||
@@ -37,6 +37,10 @@
|
||||
@apply text-black underline decoration-black;
|
||||
@apply hover:decoration-(--accent);
|
||||
}
|
||||
|
||||
h2 {
|
||||
@apply text-xl;
|
||||
}
|
||||
}
|
||||
|
||||
.content-panel {
|
||||
|
||||
10
web/src/utils/post.ts
Normal file
10
web/src/utils/post.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export function calcReadTime(wordCount: number) {
|
||||
let d = new Date()
|
||||
// avg reading rate of 184 wpm
|
||||
d.setMinutes(wordCount/184);
|
||||
if (d.getMinutes() == 0) {
|
||||
return "< 1";
|
||||
} else {
|
||||
return d.getMinutes().toLocaleString();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user