Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/components/Home.astro
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -103,9 +103,9 @@ const origin = Astro.site ?? Astro.url.origin
<span class="tb-card__summary">{library.data.description}</span>
<span class="tb-card__foot">
<span class="tb-chip">{library.data.version}</span>
{library.data.usedBy.length > 0 && (
<span class="tb-chip">{TEXT.library.usedByCount(library.data.usedBy.length)}</span>
)}
<time class="tb-chip" datetime={library.data.released}>
{releaseDate(library.data.released)}
</time>
</span>
</a>
</li>
Expand Down
6 changes: 2 additions & 4 deletions src/components/LibraryPage.astro
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand All @@ -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
Expand Down Expand Up @@ -91,7 +90,6 @@ const relations = [
<li>{TEXT.library.version} <strong>{data.version}</strong>, {TEXT.library.released} {released}</li>
<li>{TEXT.library.php} <strong>{data.php}</strong></li>
<li>{TEXT.library.license} <strong>{data.license}</strong></li>
<li>{TEXT.library.downloads} <strong>{downloads}</strong> {TEXT.library.perMonth}</li>
<li>
<a href={repositoryUrl(data.name)} target="_blank" rel="noopener noreferrer">
{TEXT.library.source} <Icon name="external" size={12} />
Expand Down
11 changes: 4 additions & 7 deletions src/content.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand All @@ -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}.`)
Expand All @@ -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,
Expand All @@ -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()),
Expand Down
8 changes: 5 additions & 3 deletions src/content/site.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -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',
Expand All @@ -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))
}
14 changes: 1 addition & 13 deletions src/content/sources.ts
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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<Response> {
const response = await fetch(url)
if (!response.ok) {
Expand Down Expand Up @@ -49,10 +44,3 @@ export async function latestRelease(name: string): Promise<Release> {
}
return { version: release.version, time: release.time }
}

export async function downloads(name: string): Promise<Downloads> {
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 }
}