From 20811f107ba31c61ee2bebafd1d2a3408f9f647c Mon Sep 17 00:00:00 2001 From: lew Date: Fri, 27 Mar 2026 19:09:39 +0000 Subject: [PATCH] feat: removed pins, and added right-aligned suffixes --- www/content/hello.md | 1 - www/public/config.yaml | 1 - www/src/content.config.ts | 3 +-- www/src/lib/format.ts | 39 +++++++++++++++++++++++++++----------- www/src/lib/txt.ts | 4 ---- www/src/pages/[slug].astro | 4 ++-- www/src/pages/index.astro | 8 ++++---- www/src/styles/global.css | 16 ++++++++++++++++ 8 files changed, 51 insertions(+), 25 deletions(-) diff --git a/www/content/hello.md b/www/content/hello.md index 4ef35ee..255e402 100644 --- a/www/content/hello.md +++ b/www/content/hello.md @@ -1,7 +1,6 @@ --- title: hello date: 2023-02-26 -pinned: true --- i've always had some sort of homepage. it was originally on bebo, then that died and i didn't ever get into other social media, so i made a website diff --git a/www/public/config.yaml b/www/public/config.yaml index 2b7aa3a..c1c9ffa 100644 --- a/www/public/config.yaml +++ b/www/public/config.yaml @@ -1,4 +1,3 @@ -pinned: [] descriptions: cv.txt: curriculum vitae now.txt: what i'm doing now diff --git a/www/src/content.config.ts b/www/src/content.config.ts index 6499a0a..914dbec 100644 --- a/www/src/content.config.ts +++ b/www/src/content.config.ts @@ -3,13 +3,12 @@ import { glob, file } from 'astro/loaders'; import { z } from 'astro/zod'; import yaml from 'js-yaml'; -const md = defineCollection({ +const posts = defineCollection({ loader: glob({ pattern: '**/*.md', base: './content' }), schema: z.object({ title: z.string(), date: z.coerce.date(), updated: z.coerce.date().optional(), - pinned: z.boolean().optional(), category: z.string().optional(), related: z.array(z.string()).optional(), }) diff --git a/www/src/lib/format.ts b/www/src/lib/format.ts index 41468a2..9257bde 100644 --- a/www/src/lib/format.ts +++ b/www/src/lib/format.ts @@ -26,28 +26,45 @@ export function formatDate(date: Date): string { return `${d}/${m}/${y}`; } +export function wordCount(markdown: string | undefined): string { + if (!markdown) return ''; + const words = markdown + .replace(/^---[\s\S]*?---/m, '') + .replace(/^#+\s+.*$/gm, '') + .replace(/!?\[([^\]]*)\]\([^)]*\)/g, '$1') + .replace(/[*_~`]/g, '') + .replace(/:[a-z]+\[([^\]]*)\]/g, '$1') + .trim() + .split(/\s+/) + .filter(Boolean).length; + if (words < 100) return `${words} words`; + const mins = Math.ceil(words / 200); + return `${mins} min`; +} + +export function extractDomain(url: string): string { + try { + return new URL(url).hostname.replace(/^www\./, ''); + } catch { + return ''; + } +} + export function formatListItem( date: Date, url: string, title: string, - options?: { pinned?: boolean; suffix?: string } + options?: { suffix?: string } ): string { - const pinnedBadge = options?.pinned ? ' [pinned]' : ''; - const suffix = options?.suffix ? ` ${options.suffix}` : ''; - return `${formatDate(date)}${title}${pinnedBadge}${suffix}`; + const suffixHtml = options?.suffix ? `${options.suffix}` : ''; + return `${formatDate(date)}${title}${suffixHtml}`; } interface Sortable { date: Date; - pinned?: boolean; } export function sortEntries(items: T[], key?: (item: T) => Sortable): T[] { const get = key ?? (item => item as unknown as Sortable); - return items.slice().sort((a, b) => { - const ak = get(a), bk = get(b); - if (ak.pinned && !bk.pinned) return -1; - if (!ak.pinned && bk.pinned) return 1; - return bk.date.getTime() - ak.date.getTime(); - }); + return items.slice().sort((a, b) => get(b).date.getTime() - get(a).date.getTime()); } diff --git a/www/src/lib/txt.ts b/www/src/lib/txt.ts index 2f0dea4..ad13389 100644 --- a/www/src/lib/txt.ts +++ b/www/src/lib/txt.ts @@ -6,12 +6,10 @@ import { sortEntries } from './format'; export interface TxtFile { name: string; date: Date; - pinned: boolean; description?: string; } export interface TxtConfig { - pinned?: string[]; descriptions?: Record; dates?: Record; } @@ -32,7 +30,6 @@ export function getTxtFiles(): TxtFile[] { if (!fs.existsSync(txtDir)) return []; const config = loadTxtConfig(); - const pinnedSet = new Set(config.pinned || []); const descriptions = config.descriptions || {}; const dates = config.dates || {}; @@ -41,7 +38,6 @@ export function getTxtFiles(): TxtFile[] { .map(name => ({ name, date: dates[name] ? new Date(dates[name]) : new Date(0), - pinned: pinnedSet.has(name), description: descriptions[name], })); return sortEntries(files); diff --git a/www/src/pages/[slug].astro b/www/src/pages/[slug].astro index 58fa84a..4f1c6a5 100644 --- a/www/src/pages/[slug].astro +++ b/www/src/pages/[slug].astro @@ -1,7 +1,7 @@ --- import { getCollection, render } from 'astro:content'; import Layout from '../layouts/Layout.astro'; -import { formatDate, formatListItem, excerpt } from '../lib/format'; +import { formatDate, formatListItem, excerpt, wordCount } from '../lib/format'; import { getSlug, resolveRelatedPosts, type Post } from '../lib/md'; export async function getStaticPaths() { @@ -21,7 +21,7 @@ const description = excerpt((post as Post).body) || undefined;

{post.data.title}

-

{formatDate(post.data.date)}{post.data.updated && ` (updated ${formatDate(post.data.updated)})`}

+

{formatDate(post.data.date)}{post.data.updated && ` (updated ${formatDate(post.data.updated)})`} · {wordCount((post as Post).body)}{post.data.category && ` · ${post.data.category}`}

{related.length > 0 && ( diff --git a/www/src/pages/index.astro b/www/src/pages/index.astro index 75f592f..59bf463 100644 --- a/www/src/pages/index.astro +++ b/www/src/pages/index.astro @@ -2,7 +2,7 @@ import { getCollection } from 'astro:content'; import Layout from '../layouts/Layout.astro'; import { getApprovedEntries, type GuestbookEntry } from '../lib/db'; -import { formatDate, formatListItem, escapeHtml } from '../lib/format'; +import { formatDate, formatListItem, extractDomain, wordCount, escapeHtml } from '../lib/format'; import { organizePostsByCategory, getSlug } from '../lib/md'; import { getTxtFiles } from '../lib/txt'; import { DEFAULT_CATEGORY, SECTIONS, SUBDOMAINS } from '../lib/consts'; @@ -37,7 +37,7 @@ const urls = [
{!isDefault && }
- `${formatListItem(post.data.date, `/${getSlug(post.id)}`, post.data.title, { pinned: post.data.pinned })}` + `${formatListItem(post.data.date, `/${getSlug(post.id)}`, post.data.title, { suffix: wordCount(post.body) })}` ).join('')} />
); @@ -47,14 +47,14 @@ const urls = [
{ const name = f.name.replace(/\.txt$/, ''); - return `${formatListItem(f.date, `/${f.name}`, name, { pinned: f.pinned })}`; + return `${formatListItem(f.date, `/${f.name}`, name, { suffix: f.description })}`; }).join('')} />
- `${formatListItem(b.data.date, b.data.url, b.data.title)}` + `${formatListItem(b.data.date, b.data.url, b.data.title, { suffix: extractDomain(b.data.url) })}` ).join('')} />
diff --git a/www/src/styles/global.css b/www/src/styles/global.css index 4332b9c..3a9212b 100644 --- a/www/src/styles/global.css +++ b/www/src/styles/global.css @@ -116,11 +116,27 @@ section pre { } .entry-content { + display: flex; overflow: hidden; white-space: nowrap; +} + +.entry-content > a { + flex: 0 1 auto; + min-width: 0; + overflow: hidden; text-overflow: ellipsis; } +.entry-suffix { + flex: 1 10000 0%; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + text-align: right; + padding-left: 1ch; +} + .guestbook-entries { font-family: monospace; white-space: pre;