import type { Transformer } from "./types.js";
import { buildEmbedSrcdoc, DEFAULT_EMBED_HEIGHT } from "../../shared/embed-doc.js";
export { buildEmbedSrcdoc };
/**
* Transforms `
`
* into:
*
*
*
*
* ...
*
*
* - The stored `height` is used as the initial `height:` on the iframe so
* the page reserves the right space before the iframe even loads
* (important with `loading=lazy`), but is NOT used as `min-height`: that
* would prevent the iframe from shrinking if the chart, on a narrower
* viewport, reports a smaller scrollHeight.
* - A small safety `min-height` keeps the iframe from collapsing to 0 while
* the embed is still loading.
* - `srcdoc` is built from the shared `buildEmbedSrcdoc` which also embeds
* the height reporter and the theme listener.
* - If `title` or `desc` is present, a is generated so the
* publisher CSS (`figure.html-embed`) can number the figure.
*/
const SAFETY_MIN_HEIGHT = 80;
export const htmlEmbedTransformer: Transformer = {
name: "htmlEmbed",
apply(document, ctx) {
for (const div of [...document.querySelectorAll('div[data-component="htmlEmbed"]')]) {
const src = div.getAttribute("src") || div.getAttribute("data-src") || "";
const rawHeight = div.getAttribute("height") || div.getAttribute("data-height");
const initialHeight = Math.max(
parseInt(rawHeight || "", 10) || DEFAULT_EMBED_HEIGHT,
SAFETY_MIN_HEIGHT,
);
const title = div.getAttribute("title") || div.getAttribute("data-title") || "";
const desc = div.getAttribute("desc") || div.getAttribute("data-desc") || "";
const embedHtml = ctx.embeds?.[src] || "";
const figure = document.createElement("figure");
figure.className = "html-embed";
if (src) figure.setAttribute("data-embed-src", src);
const container = document.createElement("div");
container.className = "html-embed-container";
const iframe = document.createElement("iframe");
iframe.setAttribute("data-embed-src", src);
iframe.setAttribute(
"style",
`width:100%;border:none;display:block;height:${initialHeight}px;min-height:${SAFETY_MIN_HEIGHT}px;background:transparent;`,
);
iframe.setAttribute("loading", "lazy");
iframe.setAttribute("sandbox", "allow-scripts allow-same-origin");
if (title) iframe.setAttribute("title", title);
iframe.setAttribute("srcdoc", embedHtml ? buildEmbedSrcdoc(embedHtml) : "");
container.appendChild(iframe);
figure.appendChild(container);
if (title || desc) {
const caption = document.createElement("figcaption");
caption.className = "html-embed__desc";
if (title && desc) {
const strong = document.createElement("strong");
strong.textContent = title;
caption.appendChild(strong);
caption.appendChild(document.createTextNode(" " + desc));
} else {
caption.textContent = title || desc;
}
figure.appendChild(caption);
}
div.replaceWith(figure);
}
},
};