hiparquia.dog — sitio F0-lite: Astro estático, cero JS, candado del protocolo en código

This commit is contained in:
2026-08-05 11:10:53 -06:00
commit 974823b9bb
23 changed files with 5294 additions and 0 deletions
+58
View File
@@ -0,0 +1,58 @@
import pw from '/home/claude/.npm-global/lib/node_modules/playwright/index.js';
import fs from 'fs';
const { chromium } = pw;
/* Las tarjetas al compartir. 1200×630 es lo que leen WhatsApp, Facebook,
Telegram y X — ninguno ejecuta JavaScript, así que la tarjeta es esta imagen
y las etiquetas og:. Sin ella, el enlace viaja desnudo.
(Lección de serclin.mx: el og:image ausente decide la tarjeta, no el sitio.) */
const TARJETAS = [
{ archivo: 'hiparquia', palabra: 'hiparquia',
pie: 'Cada verso con su ficha: la fuente, la edición y hasta dónde llegó el cotejo.',
tam: 128 },
{ archivo: 'hombres-necios', palabra: 'necios',
pie: 'Sor Juana Inés de la Cruz · Inundación castálida, Madrid, 1689',
tam: 172 },
{ archivo: 'nada-te-turbe', palabra: 'nada',
pie: 'Atribuido a Teresa de Ávila (1515–1582) · letrilla hallada en su breviario',
tam: 172 },
];
const W = 1200, H = 630;
const b64 = fs.readFileSync('src/fuentes/Commissioner-latin.woff2').toString('base64');
const pagina = (T) => `<!doctype html><meta charset="utf-8"><style>
@font-face{ font-family:Commissioner; src:url(data:font/woff2;base64,${b64}) format('woff2');
font-weight:100 900; font-display:block; }
*{margin:0;padding:0;box-sizing:border-box}
html,body{width:${W}px;height:${H}px;background:#000}
body{font-family:Commissioner;color:#fff;font-variation-settings:"FLAR" 0,"VOLM" 0;
padding:78px;display:flex;flex-direction:column;justify-content:space-between;
-webkit-font-smoothing:antialiased}
.palabra{font-weight:800;font-size:${T.tam}px;line-height:1.02;letter-spacing:-0.025em;
margin-block:auto 0}
.pie{font-weight:300;font-size:29px;line-height:1.45;color:#a6a6a6;max-width:26em;
margin-block-start:30px}
</style>
<div class="palabra">${T.palabra}</div>
<div class="pie">${T.pie}</div>`;
const b = await chromium.launch({ executablePath:'/opt/pw-browsers/chromium',
args:['--force-device-scale-factor=1','--hide-scrollbars'] });
const p = await b.newPage({ viewport:{ width:W, height:H }, deviceScaleFactor:1 });
fs.mkdirSync('public/og', { recursive:true });
const out = [];
for (const T of TARJETAS) {
await p.setContent(pagina(T));
await p.evaluate(()=>document.fonts.ready);
const f = `public/og/${T.archivo}.png`;
await p.screenshot({ path:f });
const desborde = await p.evaluate(() => {
const d = document.documentElement;
return { h: d.scrollWidth - d.clientWidth, v: d.scrollHeight - d.clientHeight };
});
out.push({ archivo:T.archivo, bytes: fs.statSync(f).size, desborde });
}
await b.close();
console.log(JSON.stringify(out, null, 1));