From 6237ff86d08efb5706057c92744f3609b5d6fc52 Mon Sep 17 00:00:00 2001 From: "D. Rimron-Soutter" Date: Thu, 1 Jan 2026 15:42:22 +0000 Subject: [PATCH] A yolo test of codex --- AGENTS.md | 2 +- example.env | 20 +++++++++- src/app/registers/[hex]/page.tsx | 65 ++++++++++++++++++++++++++++++++ src/env.ts | 16 ++++++++ 4 files changed, 101 insertions(+), 2 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index f326701..14f286c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -152,7 +152,7 @@ Comment what the code does, not what the agent has done. The documentation's pur - git commit messages: - Use imperative mood (e.g., "Add feature X", "Fix bug Y"). - Include relevant issue numbers if applicable. - - Sign-off commit message as Junie@ + - Sign-off commit message as @ ### References diff --git a/example.env b/example.env index e757c95..ebe1b81 100644 --- a/example.env +++ b/example.env @@ -1,3 +1,6 @@ +# System hostname for permalinks (mandatory) +HOSTNAME=localhost + # ZXDB MySQL connection URL # Example using a readonly user created by ZXDB scripts # CREATE ROLE 'zxdb_readonly'; @@ -15,4 +18,19 @@ ZXDB_FILEPATH=https://zxdbfiles.com/ WOS_FILEPATH=https://archive.org/download/World_of_Spectrum_June_2017_Mirror/World%20of%20Spectrum%20June%202017%20Mirror.zip/World%20of%20Spectrum%20June%202017%20Mirror/ # Local cache root where files will be mirrored (without the leading slash) -CDN_CACHE=/mnt/files/zxfiles \ No newline at end of file +CDN_CACHE=/mnt/files/zxfiles + +# Optional: File prefixes for localized mirroring or rewrite logic +# ZXDB_FILE_PREFIX= +# WOS_FILE_PREFIX= + +# OIDC Authentication configuration +# OIDC_PROVIDER_URL= +# OIDC_CLIENT_ID= +# OIDC_CLIENT_SECRET= + +# Redis cache URL (e.g. redis://host:6379) +# CACHE_URL= + +# SMTP mail URL (e.g. smtp://user:pass@host:587) +# MAIL_URL= \ No newline at end of file diff --git a/src/app/registers/[hex]/page.tsx b/src/app/registers/[hex]/page.tsx index 4e87538..3df332c 100644 --- a/src/app/registers/[hex]/page.tsx +++ b/src/app/registers/[hex]/page.tsx @@ -1,9 +1,74 @@ +import type { Metadata } from 'next'; import { notFound } from 'next/navigation'; import Link from 'next/link'; import RegisterDetail from '@/app/registers/RegisterDetail'; import {Container, Row} from "react-bootstrap"; import { getRegisters } from '@/services/register.service'; +const buildRegisterSummary = (register: { description: string; text: string; modes: { text: string }[] }) => { + const trimLine = (line: string) => line.trim(); + const isInfoLine = (line: string) => + line.length > 0 && + !line.startsWith('//') && + !line.startsWith('(R') && + !line.startsWith('(W') && + !line.startsWith('(R/W') && + !line.startsWith('*') && + !/^bits?\s+\d/i.test(line); + + const modeLines = register.modes.flatMap(mode => mode.text.split('\n')).map(trimLine).filter(isInfoLine); + const textLines = register.text.split('\n').map(trimLine).filter(isInfoLine); + const descriptionLines = register.description.split('\n').map(trimLine).filter(isInfoLine); + + const rawSummary = [...textLines, ...modeLines, ...descriptionLines].join(' ').replace(/\s+/g, ' ').trim(); + if (!rawSummary) return 'Spectrum Next register details and bit-level behavior.'; + if (rawSummary.length <= 180) return rawSummary; + return `${rawSummary.slice(0, 177).trimEnd()}...`; +}; + +export async function generateMetadata({ params }: { params: Promise<{ hex: string }> }): Promise { + const registers = await getRegisters(); + const { hex } = await params; + const targetHex = decodeURIComponent(hex).toLowerCase(); + const register = registers.find(r => r.hex_address.toLowerCase() === targetHex); + + if (!register) { + return { + title: 'Register Not Found | Spectrum Next Explorer', + robots: { index: false, follow: false }, + }; + } + + const summary = buildRegisterSummary(register); + const title = `${register.hex_address} ${register.name} | Spectrum Next Explorer`; + const imageUrl = `/registers/${register.hex_address}/opengraph-image`; + + return { + title, + description: summary, + openGraph: { + title, + description: summary, + type: 'article', + url: `/registers/${register.hex_address}`, + images: [ + { + url: imageUrl, + width: 1200, + height: 630, + alt: `${register.hex_address} ${register.name}`, + }, + ], + }, + twitter: { + card: 'summary_large_image', + title, + description: summary, + images: [imageUrl], + }, + }; +} + export default async function RegisterDetailPage({ params }: { params: Promise<{ hex: string }> }) { const registers = await getRegisters(); const { hex } = await params; diff --git a/src/env.ts b/src/env.ts index 9a08723..91c38f5 100644 --- a/src/env.ts +++ b/src/env.ts @@ -9,6 +9,22 @@ const serverSchema = z.object({ .refine((s) => s.startsWith("mysql://"), { message: "ZXDB_URL must be a valid mysql:// URL", }), + + // Optional file prefixes for ZXDB and WOS + ZXDB_FILE_PREFIX: z.string().optional(), + WOS_FILE_PREFIX: z.string().optional(), + + // OIDC Configuration + OIDC_PROVIDER_URL: z.string().url().optional(), + OIDC_CLIENT_ID: z.string().optional(), + OIDC_CLIENT_SECRET: z.string().optional(), + + // Redis cache and SMTP mail URLs + CACHE_URL: z.string().url().optional(), + MAIL_URL: z.string().url().optional(), + + // System hostname for permalinks (mandatory) + HOSTNAME: z.string().min(1), }); function formatErrors(errors: z.ZodFormattedError, string>) {