presentation/renderers/table.renderer.ts

presentation/renderers/table.renderer.ts is a file in Bane's Lab Site. 44 lines of code and 10 definitions.

import type { TableBlock, TableTone } from "#types/block.types";
import { appendChildren, createElement } from "#core/factories/element.factory";
import { fillMarkup } from "#presentation/renderers/text.renderer";

const KEYWORD_COLUMNS: ReadonlyMap<TableTone, number> = new Map([
    ["keyword", 1],
    ["contrast", 2],
]);

const renderCell = function renderCell(cell: string, index: number, tone: TableTone | undefined): Element {
    const element = createElement("td", {});
    if (tone === "role" && index === 0) {
        element.append(fillMarkup(createElement("strong", {}), cell));
        return element;
    }
    if (tone !== undefined && index < (KEYWORD_COLUMNS.get(tone) ?? 0)) {
        element.append(createElement("code", { className: "keyword", text: cell }));
        return element;
    }
    return fillMarkup(element, cell);
};

const renderHead = function renderHead(headers: readonly string[]): Element {
    const row = createElement("tr", {});
    appendChildren(
        row,
        headers.map((header) => fillMarkup(createElement("th", {}), header)),
    );
    return createElement("thead", { children: [row] });
};

const renderBody = function renderBody(block: TableBlock): Element {
    const body = createElement("tbody", {});
    for (const cells of block.rows) {
        const row = createElement("tr", {});
        appendChildren(
            row,
            cells.map((cell, index) => renderCell(cell, index, block.tone)),
        );
        body.append(row);
    }
    return body;
};

export const renderTable = function renderTable(block: TableBlock): Element {
    const className = block.tone === undefined ? "block-table" : `block-table ${block.tone}`;
    const table = createElement("table", { children: [renderHead(block.headers), renderBody(block)] });
    return createElement("div", { children: [table], className });
};