Spaces:
Runtime error
Runtime error
| import type { Transformer } from "./types.js"; | |
| import { buildEmbedSrcdoc, DEFAULT_EMBED_HEIGHT } from "../../shared/embed-doc.js"; | |
| export { buildEmbedSrcdoc }; | |
| /** | |
| * Transforms `<div data-component="htmlEmbed" src="..." title="..." desc="..." height="...">` | |
| * into: | |
| * <figure class="html-embed"> | |
| * <div class="html-embed-container"> | |
| * <iframe srcdoc="..." ... /> | |
| * </div> | |
| * <figcaption class="html-embed__desc">...</figcaption> | |
| * </figure> | |
| * | |
| * - 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 <figcaption> 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); | |
| } | |
| }, | |
| }; | |