# presentation/renderers/diagram.renderer.ts

> 73 lines of code and 14 definitions.

Tree: Site tree
Language: typescript
Layer: product
Canonical: https://banes-lab.com/anatomy/tree#file-presentation-renderers-diagram-renderer-ts
Source text: https://banes-lab.com/assets/sources/source.7f03c437222a51e2e9961a859bb51190f09c58e504eda6b01e076a8b1a1de9fe.generated.txt

## Definitions

- `createCanvas` (lexical_declaration, line 41)
- `fill` (lexical_declaration, line 28)
- `renderDiagram` (lexical_declaration, line 56, exported)
- `ratioOf` (lexical_declaration, line 21)
- `parts` (lexical_declaration, line 22)
- `width` (lexical_declaration, line 23)
- `height` (lexical_declaration, line 24)
- `vector` (lexical_declaration, line 33)
- `ratio` (lexical_declaration, line 34)
- `holder` (lexical_declaration, line 42)
- `panel` (lexical_declaration, line 43)
- `caption` (lexical_declaration, line 57, exported)
- `expand` (lexical_declaration, line 58, exported)
- `header` (lexical_declaration, line 61, exported)

## Uses

- [core/factories/element.factory.ts](https://banes-lab.com/source/tree/core/factories/element.factory.ts.md)
- [core/loaders/diagram.loader.ts](https://banes-lab.com/source/tree/core/loaders/diagram.loader.ts.md)
- [core/predicates/document.predicate.ts](https://banes-lab.com/source/tree/core/predicates/document.predicate.ts.md)
- [core/registries/style.registry.ts](https://banes-lab.com/source/tree/core/registries/style.registry.ts.md)
- [presentation/components/diagram.component.ts](https://banes-lab.com/source/tree/presentation/components/diagram.component.ts.md)

## Source

```typescript
import { DIAGRAM_MISSING, VIEW_FULL_DIAGRAM_TITLE } from "#configuration/strings/diagram.strings";
import {
    DIAGRAM_RATIO_PROPERTY,
    VIEWBOX_ATTRIBUTE,
    VIEWBOX_HEIGHT_INDEX,
    VIEWBOX_SEPARATOR,
    VIEWBOX_WIDTH_INDEX,
} from "#configuration/constants/diagram.constants";
import { LANGUAGE_ATTRIBUTE, MERMAID_LANGUAGE } from "#configuration/constants/code.constants";
import { createElement, createVectorElement } from "#core/factories/element.factory";
import { DIAGRAM_FILLED } from "#core/ids/diagram.ids";
import type { MermaidBlock } from "#types/block.types";
import type { PanelHandle } from "#types/panel.types";
import { attachDiagramWalk } from "#presentation/components/diagram.component";
import { createExpandButton } from "#presentation/components/overlay.component";
import { createPanel } from "#presentation/components/panel.component";
import { declareStyle } from "#core/registries/style.registry";
import { isStaticRender } from "#core/predicates/document.predicate";
import { loadDiagram } from "#core/loaders/diagram.loader";

const ratioOf = function ratioOf(vector: Element): number | null {
    const parts = (vector.getAttribute(VIEWBOX_ATTRIBUTE) ?? "").split(VIEWBOX_SEPARATOR).map(Number);
    const width = parts[VIEWBOX_WIDTH_INDEX] ?? 0;
    const height = parts[VIEWBOX_HEIGHT_INDEX] ?? 0;
    return width > 0 && height > 0 ? width / height : null;
};

const fill = function fill(holder: HTMLElement, canvas: HTMLElement, markup: string | null): void {
    if (markup === null) {
        holder.replaceChildren(createElement("p", { className: "diagram-missing", text: DIAGRAM_MISSING }));
        return;
    }
    const vector = createVectorElement(markup);
    const ratio = ratioOf(vector);
    if (ratio !== null) {
        declareStyle(canvas, DIAGRAM_RATIO_PROPERTY, String(ratio));
    }
    holder.replaceChildren(vector);
};

const createCanvas = function createCanvas(source: string, className: string): HTMLElement {
    const holder = createElement("div");
    const panel: PanelHandle = createPanel(holder, className, "fit");
    if (isStaticRender()) {
        return panel.element;
    }
    void loadDiagram(source).then((markup) => {
        fill(holder, panel.element, markup);
        void attachDiagramWalk(holder);
        panel.reset();
        panel.element.dispatchEvent(new Event(DIAGRAM_FILLED));
    });
    return panel.element;
};

export const renderDiagram = function renderDiagram(block: MermaidBlock): Element {
    const caption = block.caption ?? VIEW_FULL_DIAGRAM_TITLE;
    const expand = createExpandButton("diagram-expand", VIEW_FULL_DIAGRAM_TITLE, caption, () =>
        createCanvas(block.text, "diagram-full"),
    );
    const header = createElement("figcaption", {
        children: [createElement("span", { className: "diagram-caption", text: caption }), expand],
        className: "diagram-header",
    });
    return createElement("figure", {
        children: [
            header,
            createCanvas(block.text, "diagram-canvas"),
            createElement("pre", {
                attributes: { [LANGUAGE_ATTRIBUTE]: MERMAID_LANGUAGE },
                children: [createElement("code", { text: block.text })],
                className: "diagram-source",
            }),
        ],
        className: "diagram-figure",
    });
};
```
