/* * sophies.rocks * * Copyright (C) 2026 Zofia Szweda * * This file is part of sophies.rocks. * * sophies.rocks is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * sophies.rocks is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with sophies.rocks. If not, see . */ function escapeXml(str) { return String(str) .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); } async function renderPublications() { const list = document.querySelector('#recent-publications ul'); try { const res = await fetch('/publications.json'); const posts = await res.json(); if (posts.length === 0) { list.innerHTML = '
  • No publications yet.
  • '; return; } list.innerHTML = posts.map(p => `
  • ${escapeXml(p.title.trim())} ${p.date ? `
    ${escapeXml(new Date(p.date).toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' }))}
    ` : ''}
  • `).join(''); } catch (err) { console.error('Failed to load publications:', err); list.innerHTML = "
  • Couldn't load publications right now.
  • "; } } renderPublications();