# presentation/renderers/anatomy.renderer.ts

> 108 lines of code and 23 definitions.

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

## Definitions

- `select` (lexical_declaration, line 44)
- `renderFilesystem` (lexical_declaration, line 92, exported)
- `revealWhenLoaded` (lexical_declaration, line 19)
- `enableSelection` (lexical_declaration, line 41)
- `onClick` (lexical_declaration, line 53)
- `CLICK_EVENT` (lexical_declaration, line 17)
- `Explorer` (interface_declaration, line 32)
- `{ article, nodes, root, tab, tree, view }` (lexical_declaration, line 42)
- `built` (lexical_declaration, line 43)
- `element` (lexical_declaration, line 45)
- `link` (lexical_declaration, line 58)
- `href` (lexical_declaration, line 60)
- `target` (lexical_declaration, line 62)
- `release` (lexical_declaration, line 73)
- `suffix` (lexical_declaration, line 82)
- `hashed` (lexical_declaration, line 86)
- `requested` (lexical_declaration, line 87)
- `node` (lexical_declaration, line 88)
- `root` (lexical_declaration, line 93, exported)
- `article` (lexical_declaration, line 94, exported)
- `nodes` (lexical_declaration, line 98, exported)
- `tree` (lexical_declaration, line 99, exported)
- `view` (lexical_declaration, line 100, exported)

## Uses

- [core/factories/element.factory.ts](https://banes-lab.com/source/tree/core/factories/element.factory.ts.md)
- [core/predicates/document.predicate.ts](https://banes-lab.com/source/tree/core/predicates/document.predicate.ts.md)
- [presentation/components/code.component.ts](https://banes-lab.com/source/tree/presentation/components/code.component.ts.md)
- [presentation/components/folder.component.ts](https://banes-lab.com/source/tree/presentation/components/folder.component.ts.md)

## Used by

- [presentation/renderers/tab.renderer.ts](https://banes-lab.com/source/tree/presentation/renderers/tab.renderer.ts.md)

## Source

```typescript
import type { FolderNode, TreeNode } from "#types/folder.types";
import { LINE_INFIX, SOURCE_LOADED_EVENT, TREE_LINK_SELECTOR } from "#configuration/constants/anatomy.constants";
import { appendChildren, createElement } from "#core/factories/element.factory";
import { buildTree, flatten, markSelected, renderTree } from "#presentation/components/folder.component";
import { ANATOMY_PAGE } from "#core/ids/page.ids";
import { HREF_ATTRIBUTE } from "#configuration/constants/element.constants";
import { NODE_REQUESTED } from "#core/ids/walk.ids";
import type { Tab } from "#types/document.types";
import { isStaticRender } from "#core/predicates/document.predicate";
import { renderNode } from "#presentation/renderers/folder.renderer";
import { resolveTarget } from "#domain/loaders/anatomy.loader";
import { revealLine } from "#presentation/components/code.component";
import { subscribeEvent } from "#core/buses/base.bus";
import { tabLink } from "#assets/link.assets";
import { targetOf } from "#core/converters/folder.converter";

const CLICK_EVENT = "click";

const revealWhenLoaded = function revealWhenLoaded(view: Element, line: number): void {
    if (revealLine(view, line)) {
        return;
    }
    view.addEventListener(
        SOURCE_LOADED_EVENT,
        () => {
            revealLine(view, line);
        },
        { once: true },
    );
};

interface Explorer {
    readonly article: Element;
    readonly nodes: ReadonlyMap<string, TreeNode>;
    readonly root: FolderNode;
    readonly tab: string;
    readonly tree: Element;
    readonly view: Element;
}

const enableSelection = function enableSelection(explorer: Explorer): void {
    const { article, nodes, root, tab, tree, view } = explorer;
    const built = new Map<string, Element>();
    const select = function select(node: TreeNode, line: number | null): void {
        const element = built.get(node.id) ?? renderNode(root, node);
        built.set(node.id, element);
        view.replaceChildren(element);
        markSelected(tree, node.id);
        if (line !== null) {
            revealWhenLoaded(view, line);
        }
    };
    const onClick = function onClick(event: Event): void {
        if (!article.isConnected) {
            document.removeEventListener(CLICK_EVENT, onClick, true);
            return;
        }
        const link =
            event.target instanceof Element ? event.target.closest<HTMLAnchorElement>(TREE_LINK_SELECTOR) : null;
        const href = link === null ? null : link.getAttribute(HREF_ATTRIBUTE);
        const requested = href === null ? null : targetOf(href);
        const target = requested === null ? null : resolveTarget(requested);
        const node = target === null ? undefined : nodes.get(target.id);
        if (node === undefined || href === null || target === null) {
            return;
        }
        event.preventDefault();
        event.stopPropagation();
        window.history.replaceState({}, "", href);
        select(node, target.line);
    };
    document.addEventListener(CLICK_EVENT, onClick, true);
    const release = subscribeEvent(NODE_REQUESTED, (event) => {
        if (!article.isConnected) {
            release();
            return;
        }
        const node = nodes.get(event.id);
        if (node === undefined) {
            return;
        }
        const suffix = event.line === null ? "" : LINE_INFIX + String(event.line);
        window.history.replaceState({}, "", tabLink(ANATOMY_PAGE, tab, event.id + suffix));
        select(node, event.line);
    });
    const hashed = targetOf(window.location.hash);
    const requested = hashed === null ? null : resolveTarget(hashed);
    const node = requested === null ? undefined : nodes.get(requested.id);
    select(node ?? root, node === undefined || requested === null ? null : requested.line);
};

export const renderFilesystem = function renderFilesystem(tab: Tab): Element {
    const root = buildTree(tab.sections);
    const article = createElement("article", { className: "filesystem" });
    if (root === null) {
        return article;
    }
    const nodes = new Map(flatten(root).map((node) => [node.id, node] as const));
    const tree = renderTree(root);
    const view = createElement("div", { className: "filesystem-view" });
    article.append(createElement("h1", { className: "explorer-title", text: tab.label }));
    article.append(createElement("div", { children: [tree, view], className: "filesystem-body" }));
    if (isStaticRender()) {
        appendChildren(
            view,
            [...nodes.values()].map((node) => renderNode(root, node)),
        );
        markSelected(tree, root.id);
        return article;
    }
    enableSelection({ article, nodes, root, tab: tab.id, tree, view });
    return article;
};
```
