Add highlighted posts to the home page
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed

This commit is contained in:
Kaan Barmore-Genç 2024-05-19 00:12:44 -05:00
parent 6c50ff1b84
commit e26a954193
Signed by: kaan
GPG key ID: B2E280771CD62FCF
8 changed files with 158 additions and 66 deletions

View file

@ -0,0 +1,41 @@
import { readingTime } from 'reading-time-estimator';
import path from 'path';
import { readFile } from 'fs/promises';
import { slugify } from '$lib/slugify.js';
import _ from 'lodash';
export async function load() {
const allPostFiles = import.meta.glob<SvelteAllProps>('/src/routes/posts/*.md');
const iterablePostFiles = Object.entries(allPostFiles);
const markdownFilesPath = path.resolve(
process.env.npm_package_json ? path.dirname(process.env.npm_package_json) : '.',
'src',
'routes',
'posts',
);
const posts = await Promise.all(
iterablePostFiles.map(async ([filePath, resolver]) => {
const { metadata } = await resolver();
const slug = slugify(filePath);
const contents = await readFile(path.join(markdownFilesPath, `${slug}.md`), 'utf8');
return {
meta: metadata,
path: slug,
readingTime: readingTime(contents),
};
}),
);
const highlightedPosts = _.reverse(
_.sortBy(
posts.filter((post) => post.meta.highlighted),
({ meta }) => meta.date,
),
);
return { highlightedPosts };
}

View file

@ -10,6 +10,10 @@
import GithubLogo from 'phosphor-svelte/lib/GithubLogo'; import GithubLogo from 'phosphor-svelte/lib/GithubLogo';
import LinkedinLogo from 'phosphor-svelte/lib/LinkedinLogo'; import LinkedinLogo from 'phosphor-svelte/lib/LinkedinLogo';
import MastodonLogo from 'phosphor-svelte/lib/MastodonLogo'; import MastodonLogo from 'phosphor-svelte/lib/MastodonLogo';
import BlogPostList from './posts/[[page=integer]]/BlogPostList.svelte';
import Button from '$lib/Button.svelte';
export let data;
</script> </script>
<svelte:head> <svelte:head>
@ -22,7 +26,7 @@
<meta property="og:image" content={`https://bgenc.net${JpegFull}`} /> <meta property="og:image" content={`https://bgenc.net${JpegFull}`} />
</svelte:head> </svelte:head>
<div data-pagefind-body> <section data-pagefind-body>
<picture> <picture>
<source srcset={Avif} type="image/avif" /> <source srcset={Avif} type="image/avif" />
<source srcset={WebP} type="image/webp" /> <source srcset={WebP} type="image/webp" />
@ -95,7 +99,17 @@
</a> </a>
</li> </li>
</ul> </ul>
</div> </section>
{#if data.highlightedPosts.length > 0}
<section>
<h2>Highlighted Blog Posts</h2>
<BlogPostList showYear showReadingTime={false} posts={data.highlightedPosts} />
<div class="all-posts-button">
<Button href="/posts/">All Posts</Button>
</div>
</section>
{/if}
<style lang="scss"> <style lang="scss">
@import '../vars'; @import '../vars';
@ -129,4 +143,9 @@
width: 100%; width: 100%;
text-align: center; text-align: center;
} }
.all-posts-button {
max-width: 12rem;
margin: 2rem auto 0 auto;
}
</style> </style>

View file

@ -7,6 +7,7 @@ tags:
- dev - dev
- web - web
description: Here is how to make a text area that resizes automatically and has placeholder text, with no JavaScript with this clever CSS trick! description: Here is how to make a text area that resizes automatically and has placeholder text, with no JavaScript with this clever CSS trick!
highlighted: true
--- ---
The HTML elements `input` and `textarea` include a `placeholder` property. This The HTML elements `input` and `textarea` include a `placeholder` property. This

View file

@ -8,6 +8,7 @@ tags:
- dev - dev
- react - react
description: This post shows you how to use JavaScript to read CSS variables and create dynamic UIs, using SWR for seamless light & dark mode switching! description: This post shows you how to use JavaScript to read CSS variables and create dynamic UIs, using SWR for seamless light & dark mode switching!
highlighted: true
--- ---
I've been building a web app using React and TailwindCSS, with DaisyUI. But I've been building a web app using React and TailwindCSS, with DaisyUI. But

View file

@ -6,6 +6,7 @@ tags:
- svelte - svelte
- typescript - typescript
description: Making customizable components in Svelte can be hard, but check out this post on how to use Svelte with TailwindCSS to make them possible at no performance penalty. description: Making customizable components in Svelte can be hard, but check out this post on how to use Svelte with TailwindCSS to make them possible at no performance penalty.
highlighted: true
--- ---
I really like [Svelte](https://svelte.dev), but it has one big limitation I really like [Svelte](https://svelte.dev), but it has one big limitation

View file

@ -2,6 +2,7 @@
title: 'Using Shadow DOM to isolate injected browser extension components' title: 'Using Shadow DOM to isolate injected browser extension components'
date: 2024-05-18T23:08:16-05:00 date: 2024-05-18T23:08:16-05:00
description: 'I spent a weekend building a browser extension with React and TailwindCSS, but injected components can be a lot of trouble. This post explores how Shadow DOM saves the day (and your CSS sanity).' description: 'I spent a weekend building a browser extension with React and TailwindCSS, but injected components can be a lot of trouble. This post explores how Shadow DOM saves the day (and your CSS sanity).'
highlighted: true
--- ---
I recently started experimenting with building a browser extension. I'm using I recently started experimenting with building a browser extension. I'm using

View file

@ -6,6 +6,7 @@
import ArrowRight from 'phosphor-svelte/lib/ArrowRight'; import ArrowRight from 'phosphor-svelte/lib/ArrowRight';
import { format } from 'date-fns'; import { format } from 'date-fns';
import type { Post } from './+page.server'; import type { Post } from './+page.server';
import BlogPostList from './BlogPostList.svelte';
export let data; export let data;
@ -26,35 +27,14 @@
<title>Kaan Barmore-Genç's Blog Posts</title> <title>Kaan Barmore-Genç's Blog Posts</title>
</svelte:head> </svelte:head>
<ul class="years"> <ol class="years">
{#each groupPosts(data.posts).entries() as [year, posts]} {#each groupPosts(data.posts).entries() as [year, posts]}
<li> <li>
<h2>{year}</h2> <h2>{year}</h2>
<ol class="posts"> <BlogPostList {posts} />
{#each posts as post}
<a href={`/${post.path}`}>
<li>
<div>
<h5 class="post-title">
{post.meta.title}
</h5>
{#if post.meta.description}
<p class="description">{post.meta.description}</p>
{/if}
</div>
<div class="meta">
<time datetime={post.meta.date}>
{format(new Date(post.meta.date), 'MMMM d')}
</time>
<div>About {post.readingTime.text}</div>
</div>
</li>
</a>
{/each}
</ol>
</li> </li>
{/each} {/each}
</ul> </ol>
<div class="pagination-controls"> <div class="pagination-controls">
<Button disabled={data.page < 3} href={'/posts/'} <Button disabled={data.page < 3} href={'/posts/'}
@ -75,18 +55,6 @@
<style lang="scss"> <style lang="scss">
@import '../../../vars'; @import '../../../vars';
/* Restore the color of everything under the post links, except the titles */
.posts a {
color: $color-text;
}
.posts a .post-title {
color: $color-primary;
}
time {
width: 8rem;
}
.pagination-controls { .pagination-controls {
display: flex; display: flex;
justify-content: center; justify-content: center;
@ -102,43 +70,16 @@
user-select: none; user-select: none;
padding: 0.5rem 1rem; padding: 0.5rem 1rem;
} }
.post-title {
text-decoration: underline;
text-decoration-color: transparent;
transition: all var(--animation-speed) var(--animation-type);
}
a:hover .post-title {
text-decoration-color: unset;
}
.posts a {
text-decoration: none;
}
li { li {
list-style-type: none; list-style-type: none;
font-weight: normal; font-weight: normal;
} }
.years, .years {
.posts {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.years { .years {
gap: 4rem; gap: 4rem;
} }
.posts {
gap: 1.5rem;
}
.description {
font-size: 0.9rem;
margin-top: -1.4rem;
}
.meta {
display: flex;
flex-direction: row;
flex-wrap: wrap;
font-size: 0.9rem;
opacity: 0.8;
}
</style> </style>

View file

@ -0,0 +1,87 @@
<script lang="ts">
import { format } from 'date-fns';
import type { Post } from './+page.server';
import { readingTime } from 'reading-time-estimator';
export let showYear: boolean = false;
export let showReadingTime: boolean = true;
export let posts: Post[] = [];
</script>
<ol class="posts">
{#each posts as post}
<a href={`/${post.path}`}>
<li>
<div>
<h5 class="post-title">
{post.meta.title}
</h5>
{#if post.meta.description}
<p class="description">{post.meta.description}</p>
{/if}
</div>
<div class="meta">
<time datetime={post.meta.date}>
{format(new Date(post.meta.date), showYear ? 'MMMM d, yyyy' : 'MMMM d')}
</time>
{#if showReadingTime}
<div>{post.readingTime.words} words, {post.readingTime.text}</div>
{/if}
</div>
</li>
</a>
{/each}
</ol>
<style lang="scss">
@import '../../../vars';
/* Restore the color of everything under the post links, except the titles */
.posts a {
color: $color-text;
}
.posts a .post-title {
color: $color-primary;
}
time {
width: 8rem;
}
.post-title {
text-decoration: underline;
text-decoration-color: transparent;
transition: all var(--animation-speed) var(--animation-type);
}
a:hover .post-title {
text-decoration-color: unset;
}
.posts a {
text-decoration: none;
}
li {
list-style-type: none;
font-weight: normal;
}
.posts {
display: flex;
flex-direction: column;
}
.posts {
gap: 1.5rem;
}
.description {
font-size: 0.9rem;
margin-top: -1.4rem;
}
.meta {
display: flex;
flex-direction: row;
flex-wrap: wrap;
font-size: 0.9rem;
opacity: 0.8;
}
</style>