import cheerio from "cheerio";
import ejs from "ejs";
import path from "node:path";
import { MacroLiveSampleError } from "./errors.js";
import { HTMLTool, KumascriptError, slugify } from "./api/util.js";
import { render } from "../index.js";
const LIVE_SAMPLE_HTML = `
<% if (css) { %>
<% } %>
<%= sampleTitle %>
<% if (hasMathML) { %>
<% } %>
<% if (html) { %>
<%- html %>
<% } %>
<% if (js) { %>
<% } %>
`.trim();
const liveSampleTemplate = ejs.compile(LIVE_SAMPLE_HTML);
const liveSampleRE = /.*\/(runner|_sample_\.(.*))\.html($|\?.*$)/i;
function extractSlug(uri) {
const url = new URL(uri, "https://example.com");
return path.dirname(url.pathname);
}
export async function buildLiveSamplePages(uri, title, $, rawBody) {
// Given the URI, title, and rendered HTML of a document, build
// and return the HTML of the live-sample pages for the given
// document or else collect flaws
if (typeof $ == "string") {
$ = cheerio.load($);
}
return Promise.all([
...$("iframe")
.filter((i, iframe) => {
const src = $(iframe).attr("src");
return src && liveSampleRE.test(src.toLowerCase());
})
.map(async (i, iframe) => {
const iframeId = $(iframe).attr("id");
const id = slugify(iframeId.substr("frame_".length));
const iframeSrc = $(iframe).attr("src");
const result = { id, html: null, flaw: null, slug: null };
const iframeSlug = extractSlug(iframeSrc);
let slug = uri;
let ctx = $;
if (uri.toLowerCase() !== iframeSlug.toLowerCase()) {
// This means we have an transplanted live sample.
// It's deprecated but we still apply a workaround for now.
slug = iframeSlug;
result.slug = iframeSlug;
try {
const [c] = await render(slug);
ctx = c;
} catch (e) {
result.flaw = new MacroLiveSampleError(
e,
rawBody,
JSON.parse($(iframe).attr("data-token"))
);
return result;
}
}
const tool = new HTMLTool(ctx, slug);
let sampleData;
try {
sampleData = tool.extractLiveSampleObject(iframeId);
} catch (error) {
if (error instanceof KumascriptError) {
result.flaw = new MacroLiveSampleError(
error,
rawBody,
JSON.parse($(iframe).attr("data-token"))
);
return result;
}
throw error;
}
sampleData.sampleTitle = `${title} - ${id} - code sample`;
result.html = liveSampleTemplate(sampleData);
return result;
}),
]);
}