Files
racket-wiki/static/js/wiki/cmap/cmap-embed-view.js
T

59 lines
2.0 KiB
JavaScript

"use strict";
/** Render stored CMap snapshots as linked images inside wiki pages. */
export class CmapEmbedView {
constructor({ repository, conceptMaps, resolveReference, route, translate }) {
this.repository = repository;
this.conceptMaps = conceptMaps;
this.resolveReference = resolveReference;
this.route = route;
this.translate = translate;
}
async render(root) {
const embeds = Array.from(root.querySelectorAll(
".rw-cmap-embed:not([data-cmap-hydrated])"));
for (const embed of embeds) await this.renderOne(embed);
}
async renderOne(embed) {
embed.dataset.cmapHydrated = "loading";
const conceptMap = this.resolveReference(
embed.dataset.cmapReference || "", this.conceptMaps());
if (!conceptMap) {
this.showError(embed, this.translate("concept-map-not-found", "CMap not found"));
return;
}
try {
const stored = await this.repository.load(conceptMap.slug);
if (!stored.renderedSvg) {
throw new Error("This embedded CMap has no rendered image yet.");
}
embed.replaceChildren();
embed.dataset.cmapSlug = conceptMap.slug;
const link = document.createElement("a");
link.href = this.route(conceptMap.slug);
link.className = "rw-cmap-embed-link";
link.title = this.translate("embedded-concept-map-help", "Open this CMap.");
const image = document.createElement("img");
image.className = "rw-cmap-embed-image";
image.alt = conceptMap.title;
image.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(stored.renderedSvg)}`;
link.append(image);
embed.append(link);
embed.dataset.cmapHydrated = "ready";
} catch (error) {
this.showError(embed, error.message);
}
}
showError(embed, message) {
embed.dataset.cmapHydrated = "error";
embed.replaceChildren();
const node = document.createElement("p");
node.className = "error";
node.textContent = message;
embed.append(node);
}
}