From 3eb44b51f732e6f51dc6f94b1965f2d280cd638f Mon Sep 17 00:00:00 2001 From: Dave Pagurek Date: Sun, 7 Apr 2024 12:01:24 -0400 Subject: [PATCH 1/4] Fetch extra library info from NPM --- .../LibrarySourceLink/LinkCopier.tsx | 20 +++ src/components/LibrarySourceLink/index.astro | 8 ++ src/content/libraries/config.ts | 22 ++- src/layouts/LibrariesLayout.astro | 134 ++++++++++++++---- 4 files changed, 159 insertions(+), 25 deletions(-) create mode 100644 src/components/LibrarySourceLink/LinkCopier.tsx create mode 100644 src/components/LibrarySourceLink/index.astro diff --git a/src/components/LibrarySourceLink/LinkCopier.tsx b/src/components/LibrarySourceLink/LinkCopier.tsx new file mode 100644 index 0000000000..faa40215c0 --- /dev/null +++ b/src/components/LibrarySourceLink/LinkCopier.tsx @@ -0,0 +1,20 @@ +import { useState } from "preact/hooks" + +export const LinkCopier = (props: { link: string; children: any }) => { + const [copied, setCopied] = useState(false); + const onClick = () => { + navigator.clipboard.writeText( + `` + ); + setCopied(true); + } + + return ( + <> + + {props.children} + + {copied && Copied ✔️} + + ) +} diff --git a/src/components/LibrarySourceLink/index.astro b/src/components/LibrarySourceLink/index.astro new file mode 100644 index 0000000000..648725c2e2 --- /dev/null +++ b/src/components/LibrarySourceLink/index.astro @@ -0,0 +1,8 @@ +--- +const { props } = Astro; +import { LinkCopier } from './LinkCopier' +--- + + + + diff --git a/src/content/libraries/config.ts b/src/content/libraries/config.ts index e818b9d0cf..ba004d8072 100644 --- a/src/content/libraries/config.ts +++ b/src/content/libraries/config.ts @@ -1,7 +1,7 @@ import { z, defineCollection } from "astro:content"; import { author } from "../shared"; -const categories = [ +export const categories = [ "drawing", "color", "ui", @@ -21,6 +21,26 @@ const categories = [ "utils", ] as const; +export const categoryNames: { [key in (typeof categories)[number] ]: string } = { + drawing: 'Drawing', + color: 'Color', + ui: 'User Interface', + math: 'Math', + physics: 'Physics', + algorithms: 'Algorithms', + '3d': '3D', + 'ai-ml-cv': 'AI, ML, and CV', + animation: 'Animation', + shaders: 'Shaders', + language: 'Language', + hardware: 'Hardware', + sound: 'Sound', + data: 'Data', + networking: 'Networking', + export: 'Export', + utils: 'Utilities', +} + /** * Content collection for the Libraries section of the site. */ diff --git a/src/layouts/LibrariesLayout.astro b/src/layouts/LibrariesLayout.astro index e64db2008e..c4cfb9e675 100644 --- a/src/layouts/LibrariesLayout.astro +++ b/src/layouts/LibrariesLayout.astro @@ -4,37 +4,123 @@ import { getLibraryLink } from "@pages/_utils"; import type { CollectionEntry } from "astro:content"; import BaseLayout from "./BaseLayout.astro"; import { Image } from "astro:assets"; +import { categories, categoryNames } from '../content/libraries/config'; +import LibrarySourceLink from '../components/LibrarySourceLink/index.astro'; +type LibraryEntry = CollectionEntry<"libraries"> interface Props { - entries: CollectionEntry<"libraries">[]; + entries: LibraryEntry[]; title: string; } const { entries } = Astro.props; + +async function npmInfo(lib: LibraryEntry) { + try { + const res = await fetch(`https://registry.npmjs.org/${lib.data.npm}`); + const data = await res.json(); + return data; + } catch (e) { + console.error(`Could not fetch ${lib.data.name} on npm via ${lib.data.npm}!`) + throw e; + } +} + +function cdnLink(lib: LibraryEntry, data: any) { + const latestVersion = data['dist-tags'].latest + let link = `https://cdn.jsdelivr.net/npm/${lib.data.npm}@${latestVersion}`; + if (lib.data.npmFilePath) { + link += `/${lib.data.npmFilePath}`; + } + return link; +} + +function strCompare(a: string, b: string) { + if (a < b) { + return -1; + } + if (a > b) { + return 1; + } + return 0; +} + +function descriptionString(lib: LibraryEntry) { + let result = lib.data.description.trim(); + if (/\w$/.test(result)) { + result += ', by'; + } else if (/[\.!?]$/.test(result)) { + result += ' By'; + } else { + result += '. By'; + } + return result; +} + +const libraryTag = 'p-1 rounded-full border-solid border-black border mb-1 mr-1 inline-block text-xs' + +const sections = await Promise.all(categories.map(async (slug) => { + const name = categoryNames[slug]; + const sectionEntries = await Promise.all( + entries + .filter((e: LibraryEntry) => e.data.category === slug) + .sort((a: LibraryEntry, b: LibraryEntry) => strCompare(a.data.name, b.data.name)) + .map(async (lib: LibraryEntry) => { + if (lib.data.npm) { + const data = await npmInfo(lib); + const modifiedDate = new Date(data.time.modified); + const npmData = { + link: cdnLink(lib, data), + lastUpdated: `${modifiedDate.toLocaleString('default', { month: 'short' })} ${modifiedDate.getFullYear()}`, + }; + const license = lib.data.license || data.license; + return { lib, npmData, license }; + } else { + return { lib, npmData: undefined, license: lib.data.license }; + } + }) + ); + + return { slug, name, sectionEntries }; +})); --- - + {sections.map(({ slug, name, sectionEntries }) => ( + <> +

{name}

+ + + ))}
From 99e82c27d896dd124e9f05f0a1c806d71497f26e Mon Sep 17 00:00:00 2001 From: Dave Pagurek Date: Tue, 9 Apr 2024 20:16:20 -0400 Subject: [PATCH 2/4] Different tag ui --- src/layouts/LibrariesLayout.astro | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/layouts/LibrariesLayout.astro b/src/layouts/LibrariesLayout.astro index c4cfb9e675..ec759172e4 100644 --- a/src/layouts/LibrariesLayout.astro +++ b/src/layouts/LibrariesLayout.astro @@ -57,7 +57,7 @@ function descriptionString(lib: LibraryEntry) { return result; } -const libraryTag = 'p-1 rounded-full border-solid border-black border mb-1 mr-1 inline-block text-xs' +const libraryTag = 'py-1 px-2 rounded-lg bg-[var(--accent-color)] mb-1 mr-1 block text-xs' const sections = await Promise.all(categories.map(async (slug) => { const name = categoryNames[slug]; @@ -91,7 +91,7 @@ const sections = await Promise.all(categories.map(async (slug) => {

{name}