/* ===================================================================== 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 [ '', '', '', '', '', `${esc(title(doc))}`, '', // A reader who overrode their system setting has to have it applied // before the first paint, or every load of a dark sheet starts with a // white flash. That rules out sheet.js, which runs at the end of the // body — so the read happens here and the switch itself is still built // down there. The key is shared with sheet.js; keep the two in step. '