diff --git a/src/components/Home.astro b/src/components/Home.astro index bf48b5f..dcf3a91 100644 --- a/src/components/Home.astro +++ b/src/components/Home.astro @@ -5,7 +5,7 @@ */ import { libraries as allLibraries } from '../content' import { AREA_TEXT, AREAS, repositoryUrl } from '../content/catalog' -import { MAIN_ID, SITE, TEXT } from '../content/site' +import { MAIN_ID, releaseDate, SITE, TEXT } from '../content/site' import BaseLayout from '../layouts/BaseLayout.astro' import Icon from './Icon.astro' import HeroCompose from './HeroCompose.astro' @@ -103,9 +103,9 @@ const origin = Astro.site ?? Astro.url.origin {library.data.description} {library.data.version} - {library.data.usedBy.length > 0 && ( - {TEXT.library.usedByCount(library.data.usedBy.length)} - )} + diff --git a/src/components/LibraryPage.astro b/src/components/LibraryPage.astro index 2c0852f..88eca60 100644 --- a/src/components/LibraryPage.astro +++ b/src/components/LibraryPage.astro @@ -6,7 +6,7 @@ import { render } from 'astro:content' import type { Library } from '../content' import { AREA_TEXT, packagistUrl, repositoryUrl } from '../content/catalog' -import { MAIN_ID, TEXT } from '../content/site' +import { MAIN_ID, releaseDate, TEXT } from '../content/site' import BaseLayout from '../layouts/BaseLayout.astro' import Icon from './Icon.astro' @@ -21,8 +21,7 @@ const packageName = `tiny-blocks/${data.name}` const install = `composer require ${packageName}` const origin = Astro.site ?? Astro.url.origin const url = new URL(`/${data.name}/`, origin).href -const released = new Intl.DateTimeFormat('en', { dateStyle: 'medium', timeZone: 'UTC' }).format(new Date(data.released)) -const downloads = new Intl.NumberFormat('en').format(data.downloads.monthly) +const released = releaseDate(data.released) /** Search engines show about 160 characters, so a short summary is completed with what the library is. */ const completed = `${data.description} ${TEXT.library.pitch}` const description = completed.length <= 165 ? completed : data.description @@ -91,7 +90,6 @@ const relations = [
  • {TEXT.library.version} {data.version}, {TEXT.library.released} {released}
  • {TEXT.library.php} {data.php}
  • {TEXT.library.license} {data.license}
  • -
  • {TEXT.library.downloads} {downloads} {TEXT.library.perMonth}
  • {TEXT.library.source} diff --git a/src/content.config.ts b/src/content.config.ts index 40cd0ef..091fea1 100644 --- a/src/content.config.ts +++ b/src/content.config.ts @@ -6,7 +6,7 @@ import { z } from 'astro/zod' import { AREAS, CATALOG } from './content/catalog' import { dependencyGraph } from './content/graph' import { documentation } from './content/readme' -import { composerFile, downloads, latestRelease, readme } from './content/sources' +import { composerFile, latestRelease, readme } from './content/sources' const libraries = defineCollection({ loader: { @@ -15,19 +15,18 @@ const libraries = defineCollection({ const names = new Set(CATALOG.map((entry) => entry.name)) const sources = await Promise.all( CATALOG.map(async (entry) => { - const [text, composer, release, stats] = await Promise.all([ + const [text, composer, release] = await Promise.all([ readme(entry.name), composerFile(entry.name), latestRelease(entry.name), - downloads(entry.name), ]) - return { entry, text, composer, release, stats } + return { entry, text, composer, release } }), ) const graph = dependencyGraph(new Map(sources.map((source) => [source.entry.name, source.composer]))) store.clear() - for (const [index, { entry, text, composer, release, stats }] of sources.entries()) { + for (const [index, { entry, text, composer, release }] of sources.entries()) { const node = graph[index] if (node === undefined) { throw new Error(`No node of the graph for ${entry.name}.`) @@ -45,7 +44,6 @@ const libraries = defineCollection({ license: [composer.license ?? 'MIT'].flat().join(', '), version: release.version, released: release.time, - downloads: stats, dependsOn: node.dependsOn, usedBy: node.usedBy, testedWith: node.testedWith, @@ -69,7 +67,6 @@ const libraries = defineCollection({ license: z.string(), version: z.string(), released: z.string(), - downloads: z.object({ total: z.number(), monthly: z.number() }), dependsOn: z.array(z.string()), usedBy: z.array(z.string()), testedWith: z.array(z.string()), diff --git a/src/content/site.ts b/src/content/site.ts index 8ef8f8a..5c9aebe 100644 --- a/src/content/site.ts +++ b/src/content/site.ts @@ -53,8 +53,6 @@ export const TEXT = { released: 'released', php: 'PHP', license: 'License', - downloads: 'Downloads', - perMonth: 'a month', source: 'Source', packagist: 'Packagist', dependsOn: 'Stands on', @@ -67,7 +65,6 @@ export const TEXT = { headline: (title: string) => `${title} for PHP`, /** What closes the description of a library page when the summary of the library is short. */ pitch: 'A small, framework-agnostic PHP library from Tiny Blocks.', - usedByCount: (count: number) => (count === 1 ? 'used by 1 library' : `used by ${count} libraries`), }, search: { title: 'Search the libraries', @@ -82,3 +79,8 @@ export const TEXT = { }, notFound: { title: 'Page not found', lede: 'This address does not exist or has moved.', back: 'Back to home' }, } as const + +/** The day a release was published, from its ISO 8601 instant, as the site shows it: Oct 24, 2026. */ +export function releaseDate(instant: string): string { + return new Intl.DateTimeFormat('en', { dateStyle: 'medium', timeZone: 'UTC' }).format(new Date(instant)) +} diff --git a/src/content/sources.ts b/src/content/sources.ts index 6c3f284..4aa09fa 100644 --- a/src/content/sources.ts +++ b/src/content/sources.ts @@ -1,6 +1,6 @@ /** * What the site reads about each library when it is built: the README and the `composer.json` from - * its repository, and the latest release and the downloads from Packagist. A failed request fails the + * its repository, and the latest release from Packagist. A failed request fails the * build, so the site never publishes a library with half of its page missing. */ import { ORGANIZATION, rawUrl } from './catalog' @@ -17,11 +17,6 @@ export interface Release { readonly time: string } -export interface Downloads { - readonly total: number - readonly monthly: number -} - async function fetchOk(url: string): Promise { const response = await fetch(url) if (!response.ok) { @@ -49,10 +44,3 @@ export async function latestRelease(name: string): Promise { } return { version: release.version, time: release.time } } - -export async function downloads(name: string): Promise { - const body = (await (await fetchOk(`https://packagist.org/packages/${ORGANIZATION}/${name}/stats.json`)).json()) as { - downloads: Downloads - } - return { total: body.downloads.total, monthly: body.downloads.monthly } -}