presentation/renderers/page.shell.renderer.ts

presentation/renderers/page.shell.renderer.ts is a file in Bane's Lab Site. 76 lines of code and 16 definitions.

import { MISSING_PAGE_LINK, MISSING_PAGE_MESSAGE, MISSING_PAGE_TITLE } from "#configuration/strings/page.strings";
import type { RecordLink, SectionSubject } from "#types/page.types";
import { COPY_PAGE_TITLE } from "#configuration/strings/clipboard.strings";
import { HOME_PAGE } from "#core/ids/page.ids";
import { STATIC_RENDER_ATTRIBUTE } from "#configuration/constants/document.constants";
import { createCopyButton } from "#presentation/components/clipboard.component";
import { createElement } from "#core/factories/element.factory";
import { createPageLink } from "#presentation/components/link.component";
import { exportText } from "#core/converters/text.converter";
import { loadedPage } from "#domain/registries/page.registry";
import { missingSection } from "#configuration/strings/report.strings";
import { renderOwnSection } from "#presentation/renderers/tab.renderer";
import { renderSiteFooter } from "#presentation/renderers/site.renderer";
import { secondaryTab } from "#presentation/renderers/page.renderer";

const missingPage = function missingPage(): Element {
    return createElement("div", {
        children: [
            createElement("h1", { text: MISSING_PAGE_TITLE }),
            createElement("p", { text: MISSING_PAGE_MESSAGE }),
            createPageLink(HOME_PAGE, "footer-link", [MISSING_PAGE_LINK]),
        ],
        className: "missing-page",
    });
};

const asStatic = function asStatic<Result>(work: () => Result): Result {
    document.documentElement.setAttribute(STATIC_RENDER_ATTRIBUTE, "");
    try {
        return work();
    } finally {
        document.documentElement.removeAttribute(STATIC_RENDER_ATTRIBUTE);
    }
};

export const renderPage = function renderPage(page: string): readonly Element[] {
    const definition = loadedPage(page);
    const content = definition === undefined ? missingPage() : definition.render();
    const shell = createElement("div", { children: [content], className: "page-content" });
    shell.append(createCopyButton(() => exportText(shell), "copy-button large copy-all", COPY_PAGE_TITLE));
    return [shell, renderSiteFooter(definition?.license)];
};

export const renderStaticPage = function renderStaticPage(page: string): readonly Element[] {
    return asStatic(() => renderPage(page));
};

const linkOf = function linkOf(link: RecordLink): Element {
    return createElement("a", { attributes: { href: link.path ?? "" }, text: link.label });
};

export const renderSectionPage = function renderSectionPage(subject: SectionSubject): Element {
    const { seed } = subject;
    const definition = loadedPage(seed.page);
    const content = definition?.content.kind === "tabbed" ? definition.content : null;
    const tab = content?.tabs.find((candidate) => candidate.id === seed.tab);
    const draw = (): Element | null =>
        content === null || tab === undefined ? null : renderOwnSection(content.layout, tab, seed.section, seed.rows);
    const group = asStatic(draw);
    if (group === null) {
        throw new Error(missingSection(seed.page, seed.tab, seed.section));
    }
    const parts = subject.parts.map((link) => createElement("li", { children: [linkOf(link)] }));
    return createElement("article", {
        children: [
            createElement("nav", { children: [linkOf({ label: seed.tabTitle, path: seed.tabPath })] }),
            createElement("h1", { text: seed.tabTitle }),
            group,
            ...(parts.length < 2 ? [] : [createElement("ul", { children: parts, className: "section-parts" })]),
        ],
        className: "section-page",
    });
};

export const renderStaticSection = function renderStaticSection(page: string, path: string, id: string): Element | null {
    const definition = loadedPage(page);
    if (definition?.content.kind !== "tabbed") {
        return null;
    }
    const { layout, tabs } = definition.content;
    const tab = secondaryTab(definition, path) ?? tabs[0];
    return tab === undefined ? null : asStatic(() => renderOwnSection(layout, tab, id));
};