Files
libretro/website/astro.config.mjs
T
Abdessamad Derraz b5173ce72f fix: answer the search gate's missed queries
terms weighs 20, so the version table outranks MAME parts. The FAQ carries ios, iphone, ipad, the file page check my dump, and a console's regional lead names it (the PlayStation BIOS). The FAQ quotes the bootstrap's fingerprint message again. The troubleshooting page, which answers the dc/ trap, joins the pages that answer dc bios missing. The gate starts node without its compile cache.
2026-10-23 20:04:38 +02:00

149 lines
6.3 KiB
JavaScript

// The RetroBIOS site. Pages, navigation and data files are written by
// scripts/generate_site.py; this folder holds the engine's configuration,
// the components and the styles.
import { readFileSync } from 'node:fs';
import { copyFile } from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
import sitemap from '@astrojs/sitemap';
import { satteri } from '@astrojs/markdown-satteri';
import starlightSidebarTopics from 'starlight-sidebar-topics';
import starlightLinksValidator from 'starlight-links-validator';
import sidebar from './src/generated/sidebar.json' with { type: 'json' };
import lastmod from './src/generated/lastmod.json' with { type: 'json' };
import stackTables from './src/plugins/rehype-stack-tables.mjs';
import shortCode from './src/plugins/rehype-short-code.mjs';
import unbrokenTokens from './src/plugins/ec-unbroken-tokens.mjs';
const SITE = 'https://abdess.github.io';
const BASE = '/retrobios/';
// Old addresses that lead on to a page: {"/from/": "/to/"}, site paths
// written by the generator. A checkout that has not run it builds with none.
// Astro puts the base before the old address but not before the new one.
const readRedirects = () => {
let redirects;
try {
redirects = JSON.parse(readFileSync(new URL('./src/generated/redirects.json', import.meta.url), 'utf-8'));
} catch (error) {
if (error.code === 'ENOENT') return {};
throw error;
}
const withBase = (to) => (/^https?:/.test(to) || to.startsWith(BASE) ? to : BASE + to.replace(/^\//, ''));
const withoutBase = (from) => (from.startsWith(BASE) ? `/${from.slice(BASE.length)}` : from);
return Object.fromEntries(Object.entries(redirects).map(([from, to]) => [withoutBase(from), withBase(to)]));
};
// The sitemap keeps the address MkDocs gave it: sitemap.xml, beside the index.
const sitemapAlias = {
name: 'retrobios-sitemap-alias',
hooks: {
'astro:build:done': async ({ dir }) => {
const root = fileURLToPath(dir);
await copyFile(`${root}sitemap-index.xml`, `${root}sitemap.xml`);
},
},
};
export default defineConfig({
site: SITE,
base: BASE,
trailingSlash: 'always',
redirects: readRedirects(),
markdown: {
processor: satteri({
hastPlugins: [stackTables(), shortCode()],
features: {
headingAttributes: true,
definitionList: true,
// Straight quotes: curly ones would change a copied command.
smartPunctuation: false,
},
}),
},
integrations: [
starlight({
title: 'RetroBIOS',
titleDelimiter: '-',
description:
'Source-verified BIOS and firmware packs for RetroArch, Batocera, Recalbox, Lakka, RetroPie, EmuDeck, RetroBat, RetroDECK, RomM, BizHawk, ROCKNIX, KNULLI, AmberELEC, EmuELEC and MiSTer FPGA.',
// The brand mark is white on the indigo of the old header: indigo on a light page.
logo: { light: './src/assets/logo-light.svg', dark: './src/assets/logo-dark.svg', replacesTitle: false },
favicon: '/assets/brand/favicon-32.png',
head: [
{ tag: 'link', attrs: { rel: 'icon', type: 'image/svg+xml', href: `${BASE}assets/brand/favicon.svg` } },
{ tag: 'link', attrs: { rel: 'apple-touch-icon', sizes: '180x180', href: `${BASE}assets/brand/apple-touch-icon.png` } },
],
social: [{ icon: 'github', label: 'RetroBIOS on GitHub', href: 'https://github.com/Abdess/retrobios' }],
customCss: ['./src/styles/retrobios.css'],
components: {
PageTitle: './src/components/PageTitle.astro',
MarkdownContent: './src/components/MarkdownContent.astro',
Footer: './src/components/Footer.astro',
Header: './src/components/Header.astro',
Search: './src/components/Search.astro',
},
routeMiddleware: ['./src/routeData.ts'],
tableOfContents: { minHeadingLevel: 2, maxHeadingLevel: 3 },
// Commands wrap instead of scrolling, so the end of a one-liner stays
// visible, and never inside a word that holds a hyphen (`--platform`,
// `nintendo-64dd`: src/plugins/ec-unbroken-tokens.mjs). A command block
// is titled (Terminal, PowerShell) and drawn without the three window
// dots. Starlight writes the dots into each theme after the global
// style overrides, so they are set here.
expressiveCode: {
defaultProps: { wrap: true },
plugins: [unbrokenTokens()],
customizeTheme(theme) {
theme.styleOverrides.frames = { ...theme.styleOverrides.frames, terminalTitlebarDotsOpacity: '0' };
return theme;
},
},
lastUpdated: false,
pagination: true,
// Measured on the queries of tools/search_gate.py, at the centre of a
// range where all of them answer. How often a word appears counts more
// than in Starlight's defaults (0.1, 0.1, 2, 9), a page's title weighs
// ten times its text, so "dolphin" finds Dolphin, and the file names of
// a system page (its `files` field, written by sitestarlight.py) count
// half, so "scph5501" finds the Sony page without a file name winning
// every other query. Two fields name the page's subject in other words
// and weigh half a title: `aliases`, the ids setups file a system under
// (psx, dreamcast, gba), and `devices`, the handhelds and boxes a
// setup's own site names (R36S, Miyoo Mini). `consoles`, the consoles a
// manufacturer page holds (Neo Geo, WonderSwan Color), weighs as much
// as a title. `terms`, the words of a task or a message on screen (bios
// not found, which mame version, check my dump), weighs twice that: a
// field match scores below a title match, and at 10 the MAME parts,
// whose card titles name MAME files, came before the version table
// for "which mame version". All of them are
// attributes on an empty element, so no text of theirs reaches an
// excerpt.
pagefind: {
ranking: {
pageLength: 0.1,
termFrequency: 0.5,
termSaturation: 1.4,
termSimilarity: 9,
metaWeights: { title: 10, files: 0.5, aliases: 5, devices: 5, consoles: 10, terms: 20 },
},
},
plugins: [
starlightSidebarTopics(sidebar.topics, sidebar.options),
starlightLinksValidator(),
],
}),
// A page that states its own date (an emulator page: the day its
// profile was last read against the source) gives it to the sitemap.
// The others get no lastmod rather than the build date.
sitemap({
serialize(item) {
const date = lastmod[new URL(item.url).pathname];
return date ? { ...item, lastmod: date } : item;
},
}),
sitemapAlias,
],
});