/* * 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();