diff --git a/src/content/links.tsx b/src/content/links.tsx index c432367..13c0ff7 100644 --- a/src/content/links.tsx +++ b/src/content/links.tsx @@ -12,6 +12,7 @@ interface LinkData { description?: string, read?: string, author?: string, + quote?: string, } interface Data { links: LinkData[]; @@ -23,13 +24,81 @@ interface Data { function Link(props: { link: LinkData }) { const link = props.link; return <> - {link.title} - {" "} - {link.tags.join(", ")} +
+

+ {link.title} + {link.author ? – {link.author} : null} +

+

+ {link.tags.join(", ")} + {link.read ? <> + , read: + : null} +

+
+ {link.quote ?
+ {link.quote} +
: null} + {link.description ?

+ {link.description} +

: null} + {link.altUrls ?

+ Also available at {link.altUrls.map(url => {url})}. +

: null} + {link.related ?

+ Related {link.related}. +

: null} + {link.via ?

+ Via {link.via}. +

: null} } const data: Data = eval(`(${readFileSync("src/content/links.jsonc", "utf8")})`); data.links.pop(); // Remove template at the end + +function compare(a: string, b: string) { + return Number(a > b) - Number(b > a); +} + +function* groupBy(items: Iterable, keyFn: (item: T) => K) { + let oldKey: K = Symbol() as any; + let group: T[] | undefined = undefined; + for (const item of items) { + let newKey = keyFn(item); + if (!Object.is(newKey, oldKey)) { + if (group) { + yield [oldKey, group] as [K, T[]]; + } + group = []; + oldKey = newKey; + } + group!.push(item); + } + if (group) { + yield [oldKey, group] as [K, T[]]; + } +} + +const byDate = data.links.filter(link => link.read).sort((a, b) => -compare(a.read!, b.read!)); +const byMonth = groupBy(byDate, link => link.read!.slice(0, 7)); +const byYearMonth = [...groupBy(byMonth, month => month[0].slice(0, 4))]; +const other = data.links.filter(link => !link.read); +const monthNames = [ + "", // padding to make mapping start at 1 + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December", +]; + const title = "Links!"; export const links: Page = { title, @@ -37,8 +106,27 @@ export const links: Page = { content:

{title}

-
    - { data.links.map(link =>
  • )} +

    + Here be interesting things I've read, watched, listened to or otherwise found useful as resources over the years. These are ordered by when I read them as that seems most practical to me. +

    + {byYearMonth.map(([year, months]) =>
    +

    {year}

    + {months.map(([yearMonth, links]) =>
    +

    {monthNames[Number.parseInt(yearMonth.slice(5))]}

    +
      + {links.map(link => )} +
    +
    )} +
    )} +

    + Resources and other things +

    +
      + {other.map(link => )}
diff --git a/web/assets/styles/base.css b/web/assets/styles/base.css index 47b3f38..9ef6354 100644 --- a/web/assets/styles/base.css +++ b/web/assets/styles/base.css @@ -14,6 +14,10 @@ html { text-size-adjust: none; } +:is(ul, ol)[role="list"] { + list-style: none; +} + h1, h2, h3, h4, button, input, label { line-height: 1.1; } @@ -44,12 +48,12 @@ html { scrollbar-gutter: stable; } -hgroup h1 { - margin-bottom: 0.1em; +hgroup :is(h1, h2, h3, h4) { + margin-block-start: 0; + margin-block-end: 0.1em; } hgroup p { font-style: italic; - margin-bottom: 1em; } h1, h2, h3, h4 { @@ -57,11 +61,21 @@ h1, h2, h3, h4 { margin-block-end: 0.5em; } -:is(p, ol, ul) + :is(p, ol, ul) { - padding-block-start: 1em; +:is(hgroup, p, blockquote, ol, ul, li) + :is(hgroup, blockquote, p, ol, ul, li) { + margin-block-start: var(--block-space, 1em); } -ol, ul { +blockquote { + padding-inline: 1.25em; +} +blockquote::before { + content: "“"; +} +blockquote::after { + content: "”"; +} + +:is(ol, ul):not([role]) { padding-inline-start: 1.25em; } @@ -102,13 +116,24 @@ body { gap: 1em; margin-block: 1em; } -.author h1 { - margin-block-start: 0; -} .author p { margin-block-end: 0; } +/* links */ +.no-break { + display: inline-block; + max-width: 100%; +} +.link { + background-color: color-mix(in oklab, Canvas 90%, white); + padding: 0.5em; + border-radius: 0.5em; +} +.link>* { + --block-space: 0.5em; +} + /* sandbox */ .sandbox-inset-3d { contain: paint;