import { Tooltip } from "./tooltip.js"; /** * Load and display rendered wiki-page content as a concept description. * * DescriptionPreview caches rendered pages for the lifetime of the workspace. * A sequence token prevents a slow request from replacing a newer preview. */ export class DescriptionPreview { constructor(loadPage, renderMarkdown) { const element = document.createElement("div"); element.id = "cmap-description-tooltip"; element.className = "cmap-description-tooltip hidden"; element.setAttribute("role", "tooltip"); document.body.append(element); this.tooltip = new Tooltip(element); this.loadPage = loadPage; this.renderMarkdown = renderMarkdown; this.cache = new Map(); this.sequence = 0; } hide() { this.sequence += 1; this.tooltip.hide(); } clear() { this.cache.clear(); this.hide(); } /** Load a referenced wiki page and show it beside the supplied anchor. */ async show(anchor, reference, loadingText = "Loading…") { if (!anchor.classList.contains("is-filled") || !reference) return; const sequence = ++this.sequence; this.tooltip.show(anchor); this.tooltip.setText(loadingText); try { let preview = this.cache.get(reference); if (preview === undefined) { const page = await this.loadPage(reference); preview = String(page.markdown || "").trim() ? this.renderMarkdown(page.markdown, page.slug) : null; this.cache.set(reference, preview); } if (sequence !== this.sequence) return; if (!preview) { anchor.classList.remove("is-filled"); anchor.classList.add("is-empty"); this.tooltip.hide(); return; } this.tooltip.setHtml(`
${preview}
`); } catch (error) { if (sequence !== this.sequence) return; anchor.classList.remove("is-filled"); anchor.classList.add("is-empty"); this.tooltip.hide(); if (error.status !== 404) console.error(error); } } }