This commit is contained in:
Henry Hiles 2023-06-21 11:23:43 -04:00
parent c0a63a4a97
commit 2c103f70ae
18 changed files with 205 additions and 84 deletions

View file

@ -15,6 +15,6 @@
"@types/marked": "^5.0.0",
"astro": "^2.6.4",
"astro-icon": "^0.8.1",
"marked": "^5.1.0"
"micromark": "^3.2.0"
}
}

10
pnpm-lock.yaml generated
View file

@ -6,7 +6,7 @@ specifiers:
'@types/marked': ^5.0.0
astro: ^2.6.4
astro-icon: ^0.8.1
marked: ^5.1.0
micromark: ^3.2.0
dependencies:
',mmarked': link:@types/,mmarked
@ -14,7 +14,7 @@ dependencies:
'@types/marked': 5.0.0
astro: 2.6.4
astro-icon: 0.8.1
marked: 5.1.0
micromark: 3.2.0
packages:
@ -1868,12 +1868,6 @@ packages:
resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==}
dev: false
/marked/5.1.0:
resolution: {integrity: sha512-z3/nBe7aTI8JDszlYLk7dDVNpngjw0o1ZJtrA9kIfkkHcIF+xH7mO23aISl4WxP83elU+MFROgahqdpd05lMEQ==}
engines: {node: '>= 18'}
hasBin: true
dev: false
/mdast-util-definitions/5.1.2:
resolution: {integrity: sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==}
dependencies:

View file

@ -2,27 +2,56 @@
import styles from "../styles/BlogPost.module.css"
import Divider from "../components/Divider.astro"
import type { CollectionEntry } from "astro:content"
import { CollectionEntry, getCollection } from "astro:content"
interface Props {
post: CollectionEntry<"blog">
standalone?: Boolean
}
const { data: post, render } = Astro.props.post
const { post: postEntry, standalone = true } = Astro.props
const { data: post, render } = postEntry
const { Content } = await render()
const pubDate = new Intl.DateTimeFormat("en-US", {
month: "long",
day: "numeric",
year: "numeric"
}).format(post.pubDate)
const blog = await getCollection("blog")
const index = blog.findIndex((blogPost) => blogPost.id === postEntry.id)
const prev = blog[index - 1]
const next = blog[index + 1]
---
<section class={styles.jumbo}>
<span class={styles.date}>{pubDate}</span>
<section class={`${styles.jumbo} ${standalone ? styles.standalone : ""}`}>
<section class={styles.top}>
{standalone && <a href="/blog">&lt; Go Back</a>}
<span class={styles.date}>{pubDate}</span>
</section>
<h2 class={styles.title}>
{post.title}
</h2>
<Divider />
<article class={styles.description}>
<Content />
{standalone ? <Content /> : post.description}
</article>
{standalone ? "" : <span class={styles.more}>Read More</span>}
{
standalone ? (
<section class={styles.links}>
{prev ? (
<a href={`/blog/${prev.slug}`}>&lt; {prev.data.title}</a>
) : (
<span>&lt; Previous Article</span>
)}
{next ? (
<a href={`/blog/${next.slug}`}>{next.data.title} &gt;</a>
) : (
<span>Next Article &gt;</span>
)}
</section>
) : (
""
)
}
</section>

View file

@ -1,6 +0,0 @@
---
title: "Welcome to my blog!"
pubDate: 1687027268667
---
# **Test**

View file

@ -1,6 +0,0 @@
---
title: "Welcome to my blog!"
pubDate: 1687027268667
---
# **Test**

View file

@ -1,6 +0,0 @@
---
title: "Welcome to my blog!"
pubDate: 1687027268667
---
# **Test**

View file

@ -1,6 +0,0 @@
---
title: "Welcome to my blog!"
pubDate: 1687027268667
---
# **Test**

View file

@ -1,6 +0,0 @@
---
title: "Welcome to my blog!"
pubDate: 1687027268667
---
# **Test**

View file

@ -0,0 +1,10 @@
---
title: "Welcome to my blog!"
pubDate: 1687027268667
category: "other"
description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
---
Lorem ipsum dolor sit **amet**, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit **amet**, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

View file

@ -0,0 +1,8 @@
---
title: "Welcome to my blog!"
pubDate: 1687027268667
category: "other"
description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
---
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

View file

@ -1,4 +1,8 @@
---
title: "Welcome to my blog!"
pubDate: 1687027268667
category: "other"
description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
---
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

View file

@ -3,24 +3,26 @@ import { rssSchema } from "@astrojs/rss"
const blogCollection = defineCollection({
type: "content",
schema: rssSchema
schema: rssSchema.extend({
category: z.enum(["web", "bot", "linux", "other"])
})
})
const projectsCollection = defineCollection({
type: "content",
schema: z.object({
name: z.string(),
github: z.string().optional(),
github: z.string().url().optional(),
overview: z.string(),
customLink: z
.object({
name: z.string(),
url: z.string()
url: z.string().url()
})
.optional(),
mainImage: z.string(),
thumbImage: z.string(),
demoLink: z.string().optional()
demoLink: z.string().url().optional()
})
})

View file

@ -12,6 +12,23 @@ const posts = await getCollection("blog")
<div class={styles.container}>
<aside class={styles.sidebar}>
<input type="text" placeholder="Search..." id="search" />
<section class={styles.radios}>
<input type="radio" name="category" id="all" checked />
<label for="all">All</label>
<input type="radio" name="category" id="linux" />
<label for="linux">Linux</label>
<input type="radio" name="category" id="web" />
<label for="web">Web Development</label>
<input type="radio" name="category" id="bot" />
<label for="bot">Discord Bot Development</label>
<input type="radio" name="category" id="other" />
<label for="other">Other</label>
</section>
</aside>
<div class={styles.right}>
<article class={styles.description}>
@ -29,9 +46,9 @@ const posts = await getCollection("blog")
class={styles.link}
href={`/blog/${post.slug}`}
data-title={post.data.title}
data-tags=""
data-category={post.data.category}
>
<BlogPost post={post} />
<BlogPost post={post} standalone={false} />
</a>
))
}
@ -40,23 +57,63 @@ const posts = await getCollection("blog")
</Layout>
<script>
let category = "all"
const searchBar = document.querySelector("#search") as HTMLInputElement
const posts = document.querySelectorAll(
"[data-title]"
) as NodeListOf<HTMLElement>
const radios = document.querySelectorAll('input[type="radio"]')
const urlParams = new URLSearchParams(location.search)
const set = (name: string, value: string) => {
urlParams.set(name, value)
history.replaceState({}, "", `?${urlParams}`)
}
radios.forEach((radio) =>
radio.addEventListener("click", ({ target }) => {
if (target instanceof HTMLInputElement) {
set("category", target.id)
category = target.id
filterByCategory()
}
})
)
const search = () =>
posts.forEach((post) =>
post.setAttribute(
"aria-hidden",
post.dataset.title
filter(
(post) =>
!!post.dataset.title
?.toLowerCase()
?.includes(searchBar.value.toLowerCase())
? "false"
: "true"
)
)
searchBar?.addEventListener("input", search)
addEventListener("load", search)
const filterByCategory = () =>
filter((post) =>
category == "all" ? true : post.dataset.category == category
)
const filter = (condition: (element: HTMLElement) => boolean) =>
posts.forEach((post) =>
post.setAttribute("aria-hidden", (!condition(post)).toString())
)
searchBar?.addEventListener("input", () => {
set("search", searchBar.value)
search()
})
addEventListener("load", () => {
searchBar.value = urlParams.get("search") ?? ""
Array.from(radios).find((radio) => {
if (
radio instanceof HTMLInputElement &&
radio.id == urlParams.get("category")
) {
radio.checked = true
category = radio.id
}
})
search()
filterByCategory()
})
</script>

View file

@ -1,6 +1,6 @@
import rss from "@astrojs/rss"
import { getCollection } from "astro:content"
import { marked } from "marked"
import { micromark } from "micromark"
export const get = async (context) => {
const blog = await getCollection("blog")
@ -11,10 +11,7 @@ export const get = async (context) => {
site: context.site,
items: blog.map((post) => ({
link: `/blog/${post.slug}/`,
content: marked.parse(post.body, {
mangle: false,
headerIds: false
}),
content: micromark(post.body),
...post.data
})),
customData: "<language>en-us</language>",

View file

@ -1,9 +1,7 @@
.link {
display: flex;
text-decoration: none;
width: 100%;
color: unset;
text-decoration: none;
justify-content: center;
}
.description {
@ -35,6 +33,7 @@
.sidebar {
display: flex;
position: sticky;
gap: 1rem;
top: 8rem;
height: 80vh;
flex-direction: column;
@ -47,6 +46,21 @@
width: 100%;
}
[aria-hidden="true"] {
[aria-hidden="true"],
.radios [type="radio"] {
display: none;
}
.radios :checked + label {
color: var(--primary);
font-weight: bold;
}
label {
font-size: 1.3rem;
}
.radios {
display: flex;
flex-direction: column;
}

View file

@ -1,15 +1,38 @@
.jumbo {
display: flex;
padding: 1rem 1.5rem;
flex-direction: column;
position: relative;
align-items: center;
}
.jumbo.standalone {
max-width: 80rem;
}
.more {
margin-top: 1.5rem;
padding: 1rem;
border: 2px solid var(--primary);
border-radius: 20rem;
backdrop-filter: blur(2rem);
background: rgb(0 0 0 / 0.3);
box-shadow: 0 0 2rem black;
transition: scale 0.2s;
}
.more:hover {
scale: 1.05;
text-decoration: underline;
}
.date {
position: absolute;
top: 1rem;
right: 1rem;
color: hsl(37 10% 58%);
color: var(--muted);
}
.top {
display: flex;
justify-content: space-between;
width: 100%;
}
.title {
@ -18,9 +41,9 @@
text-align: center;
}
.description p {
.description {
font-size: 1.3rem;
max-width: 40rem;
max-width: 60rem;
text-align: justify;
}
@ -37,8 +60,20 @@
font-size: 1.6rem;
}
.description :is(strong, em) {
display: block;
.links {
width: 100%;
text-align: justify;
display: flex;
justify-content: space-between;
}
.links * {
font-size: 1.2rem;
}
.links a {
color: white;
}
.links span {
color: var(--muted);
}

View file

@ -3,8 +3,8 @@
background: rgb(0 0 0 / 0.1);
border: 2px solid var(--primary);
backdrop-filter: blur(2rem);
border-radius: 2rem;
padding: 2rem;
border-radius: 1.5rem;
padding: 1.5rem;
text-decoration: none;
white-space: nowrap;
height: 100%;

View file

@ -2,8 +2,9 @@
color-scheme: dark light;
scroll-behavior: smooth;
--primary: #4e94e4;
--secondary: #354b5f;
--primary: hsl(212, 74%, 60%);
--secondary: hsl(209, 28%, 29%);
--muted: hsl(0, 0%, 54%);
}
body {
@ -40,7 +41,7 @@ main {
align-items: center;
}
:is(article, section, aside):not(section *, nav *, header *) {
:is(article, section, aside):not(section *, nav *, header *, aside *) {
display: flex;
flex-direction: column;
border-radius: 1rem;
@ -52,7 +53,7 @@ main {
}
:is(article, section, aside):not(section *, nav *, header *):hover {
scale: 102%;
scale: 101.5%;
}
@media (min-width: 500px) {