Fix some alignment issues, add reading time estimates

This commit is contained in:
Kaan Barmore-Genç 2024-05-06 00:31:55 -05:00
parent 5e8eb94d6b
commit 25f07fd9bb
Signed by: kaan
GPG key ID: B2E280771CD62FCF
6 changed files with 57 additions and 29 deletions

24
package-lock.json generated
View file

@ -8,11 +8,13 @@
"name": "bgenc.net-new",
"version": "0.0.1",
"dependencies": {
"@sveltejs/adapter-static": "^2.0.3"
"@sveltejs/adapter-static": "^2.0.3",
"reading-time-estimator": "^1.11.0"
},
"devDependencies": {
"@sveltejs/kit": "^1.27.6",
"@types/lodash": "^4.14.201",
"@types/node": "^20.12.8",
"@typescript-eslint/eslint-plugin": "^6.11.0",
"@typescript-eslint/parser": "^6.11.0",
"date-fns": "^2.30.0",
@ -360,6 +362,15 @@
"integrity": "sha512-y9euML0cim1JrykNxADLfaG0FgD1g/yTHwUs/Jg9ZIU7WKj2/4IW9Lbb1WZbvck78W/lfGXFfe+u2EGfIJXdLQ==",
"dev": true
},
"node_modules/@types/node": {
"version": "20.12.8",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.8.tgz",
"integrity": "sha512-NU0rJLJnshZWdE/097cdCBbyW1h4hEg0xpovcoAQYHl8dnEyp/NAOiE45pvc+Bd1Dt+2r94v2eGFpQJ4R7g+2w==",
"devOptional": true,
"dependencies": {
"undici-types": "~5.26.4"
}
},
"node_modules/@types/pug": {
"version": "2.0.9",
"dev": true,
@ -2356,6 +2367,11 @@
"node": ">=8.10.0"
}
},
"node_modules/reading-time-estimator": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/reading-time-estimator/-/reading-time-estimator-1.11.0.tgz",
"integrity": "sha512-2813WXSxCPsDvgrYq+cPBI4gGqgmtKlo62rpI0mwnhrMfZJIqbDfOeidr9Y36OruDesQGmYA9DkVRmvsBbv2DA=="
},
"node_modules/regenerator-runtime": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
@ -2966,6 +2982,12 @@
"node": ">=14.0"
}
},
"node_modules/undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
"devOptional": true
},
"node_modules/unist-util-stringify-position": {
"version": "2.0.3",
"dev": true,

View file

@ -14,6 +14,7 @@
"devDependencies": {
"@sveltejs/kit": "^1.27.6",
"@types/lodash": "^4.14.201",
"@types/node": "^20.12.8",
"@typescript-eslint/eslint-plugin": "^6.11.0",
"@typescript-eslint/parser": "^6.11.0",
"date-fns": "^2.30.0",
@ -34,6 +35,7 @@
},
"type": "module",
"dependencies": {
"@sveltejs/adapter-static": "^2.0.3"
"@sveltejs/adapter-static": "^2.0.3",
"reading-time-estimator": "^1.11.0"
}
}

View file

@ -14,7 +14,9 @@
<style>
a,
button {
display: inline-block;
display: flex;
flex-direction: row;
align-items: center;
color: hsl(var(--color-text-h), var(--color-text-s), calc(100% - var(--color-text-l)));
font-weight: 600;
text-decoration: none;

View file

@ -8,8 +8,8 @@
</script>
<header>
<a href="/">
<picture class="logo">
<a class="logo" href="/">
<picture>
<source srcset={Avif} type="image/avif" />
<source srcset={WebP} type="image/webp" />
<img
@ -31,9 +31,11 @@
align-items: center;
margin-right: 4rem;
gap: 2rem;
margin-bottom: -3rem;
}
.logo {
width: 12rem;
align-self: flex-start;
}
</style>

View file

@ -1,4 +1,10 @@
import _ from 'lodash';
import { readingTime } from 'reading-time-estimator';
import path from 'path';
import { fileURLToPath } from 'url';
import { readFile } from 'fs/promises';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const PAGE_SIZE = 10;
@ -7,15 +13,18 @@ export async function load({ params }) {
const iterablePostFiles = Object.entries(allPostFiles);
const posts = await Promise.all(
iterablePostFiles.map(async ([path, resolver]) => {
iterablePostFiles.map(async ([filePath, resolver]) => {
const { metadata } = await resolver();
const slug = /[/]([^/]*)[.]md$/.exec(path)?.[1];
if (!slug) throw new Error(`Could not parse slug from path: ${path}`);
const slug = /[/]([^/]*)[.]md$/.exec(filePath)?.[1];
if (!slug) throw new Error(`Could not parse slug from path: ${filePath}`);
const contents = await readFile(path.join(__dirname, '..', `${slug}.md`), 'utf8');
return {
meta: metadata,
path: slug,
readingTime: readingTime(contents),
};
}),
);
@ -33,3 +42,4 @@ export async function load({ params }) {
pageCount: Math.ceil(posts.length / PAGE_SIZE),
};
}
export type Post = Awaited<ReturnType<typeof load>>['posts'][number];

View file

@ -1,11 +1,13 @@
<script lang="ts">
import Button from '$lib/Button.svelte';
import { ArrowLeft, ArrowLineLeft, ArrowLineRight, ArrowRight } from 'phosphor-svelte';
import { format } from 'date-fns';
import type { Post } from './+page.server';
export let data;
function groupPosts(posts: any[]) {
const postsByYear = new Map<string, any[]>();
function groupPosts(posts: Post[]) {
const postsByYear = new Map<string, Post[]>();
posts.forEach((post) => {
const year = format(new Date(post.meta.date), 'yyyy');
if (!postsByYear.has(year)) {
@ -31,6 +33,7 @@
<time datetime={post.meta.date}>
{format(new Date(post.meta.date), 'MMMM d')}
</time>
<span>about {post.readingTime.text}</span>
</li>
</a>
{/each}
@ -40,16 +43,14 @@
</ul>
<div class="pagination-controls">
<Button disabled={data.page < 3} href={'/posts/'}>{data.page < 3 ? '_' : data.page - 1}</Button>
<Button disabled={data.page < 3} href={'/posts/'}><ArrowLineLeft /></Button>
<Button disabled={data.page === 1} href={data.page === 2 ? '/posts/' : `/posts/${data.page - 1}`}
>{data.page === 1 ? '_' : data.page - 1}</Button
><ArrowLeft /></Button
>
<span class="current-page">{data.page}</span>
<Button disabled={!data.hasMore} href="/posts/{data.page + 1}"
>{data.hasMore ? data.page + 1 : '_'}</Button
>
<Button disabled={!data.hasMore} href="/posts/{data.page + 1}"><ArrowRight /></Button>
<Button disabled={data.page > data.pageCount - 2} href="/posts/{data.pageCount}"
>{data.page > data.pageCount - 2 ? '_' : data.pageCount}</Button
><ArrowLineRight /></Button
>
</div>
@ -65,25 +66,14 @@
gap: 0.2rem;
margin-top: 2rem;
}
:global(.pagination-controls > :first-child) {
margin-right: 1rem;
}
:global(.pagination-controls > :last-child) {
margin-left: 1rem;
}
.current-page {
display: inline-block;
color: hsl(var(--color-text-h), var(--color-text-s), calc(100% - var(--color-text-l)));
font-weight: 600;
text-decoration: none;
opacity: 0.6;
font-weight: bolder;
color: var(--color-primary);
cursor: unset;
user-select: none;
background-color: var(--color-primary);
padding: 0.5rem 1rem;
clip-path: var(--clip-path-button);
transition: all var(--animation-speed) var(--animation-type);
}
.post-title {
margin-bottom: 0.3rem;