presentation/renderers/surface.renderer.ts

presentation/renderers/surface.renderer.ts is a file in Bane's Lab Site. 63 lines of code and 11 definitions.

import { LANGUAGE_ATTRIBUTE, TEXT_LANGUAGE } from "#configuration/constants/code.constants";
import { MALFORMED_RECORDING, missingRecording } from "#configuration/strings/report.strings";
import {
    SURFACE_CONTROLS_CLASS,
    SURFACE_FIGURE_ATTRIBUTE,
    SURFACE_FIGURE_CLASS,
    SURFACE_STAGE_CLASS,
    SURFACE_TRANSCRIPT_CLASS,
} from "#configuration/constants/surface.constants";
import { SURFACE_MISSING } from "#configuration/strings/surface.strings";
import type { SurfaceBlock } from "#types/block.types";
import { SurfacePlayer } from "#presentation/widgets/surface.widget";
import type { SurfaceRecording } from "#types/surface.types";
import { createElement } from "#core/factories/element.factory";
import { isRecording } from "#core/predicates/surface.predicate";
import { isStaticRender } from "#core/predicates/document.predicate";
import { loadRecording } from "#domain/loaders/surface.loader";
import { transcriptOf } from "#domain/converters/surface.converter";

export const renderSurface = function renderSurface(block: SurfaceBlock): Element {
    const controls = createElement("span", { className: SURFACE_CONTROLS_CLASS });
    const stage = createElement("div", { className: SURFACE_STAGE_CLASS });
    const header = createElement("figcaption", {
        children: [createElement("span", { className: "diagram-caption", text: block.caption }), controls],
        className: "diagram-header",
    });
    const figure = createElement("figure", {
        attributes: { [SURFACE_FIGURE_ATTRIBUTE]: block.figure },
        children: [header, stage],
        className: SURFACE_FIGURE_CLASS,
    });
    if (!isStaticRender()) {
        void loadRecording(block.figure).then((recording) => {
            if (recording === null) {
                stage.replaceChildren(createElement("p", { className: "diagram-missing", text: SURFACE_MISSING }));
                return;
            }
            void new SurfacePlayer({ controls, figure, stage }, recording).start();
        });
    }
    return figure;
};

const transcriptBlock = function transcriptBlock(recording: SurfaceRecording): Element {
    const code = createElement("code", { text: transcriptOf(recording) });
    return createElement("pre", {
        attributes: { [LANGUAGE_ATTRIBUTE]: TEXT_LANGUAGE },
        children: [code],
        className: SURFACE_TRANSCRIPT_CLASS,
    });
};

export const renderTranscripts = function renderTranscripts(root: Element, recordings: readonly unknown[]): void {
    const valid = recordings.filter(isRecording);
    if (valid.length !== recordings.length) {
        throw new Error(MALFORMED_RECORDING);
    }
    for (const figure of root.querySelectorAll(`[${SURFACE_FIGURE_ATTRIBUTE}]`)) {
        const name = figure.getAttribute(SURFACE_FIGURE_ATTRIBUTE) ?? "";
        const recording = valid.find((entry) => entry.figure === name);
        if (recording === undefined) {
            throw new Error(missingRecording(name));
        }
        figure.querySelector(`.${SURFACE_STAGE_CLASS}`)?.replaceChildren(transcriptBlock(recording));
    }
};