/* ===================================================================== Assembling and reading whole sheet files. The preview iframe and the exported file are built from the same renderer, so what you arrange on the canvas is what lands on disk. The only difference is that the preview carries editing chrome and omits the click-to-copy script, because on the canvas a click selects. ===================================================================== */ import { renderBody } from './render.js'; let cache = null; export async function assets() { if (!cache) { const [css, js, logo] = await Promise.all([ fetch('./sheet.css').then((r) => r.text()), fetch('./sheet.js').then((r) => r.text()), fetch('./logo.txt').then((r) => r.text()).catch(() => ''), ]); cache = { css, js, logo: logo.trim() }; } return cache; } const esc = (s) => String(s).replace(/[&<>]/g, (c) => ({ '&': '&', '<': '<', '>': '>' }[c])); function title(doc) { const code = (doc.meta.courseCode || '').trim() || 'Exercise'; return `${code} · ${doc.meta.exercise} · ${doc.meta.title}`; } /** A complete, self-contained sheet — what Export writes. */ export function wholeFile(doc, { css, js }) { return [ '', '', '
', '', '', `