# presentation/renderers/text.renderer.ts

> 64 lines of code and 11 definitions.

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

## Definitions

- `fillMarkup` (lexical_declaration, line 69, exported)
- `renderRun` (lexical_declaration, line 19)
- `renderMarkup` (lexical_declaration, line 45)
- `renderInside` (lexical_declaration, line 41)
- `isEmphasized` (lexical_declaration, line 37)
- `plainText` (lexical_declaration, line 63, exported)
- `NO_CLASS` (lexical_declaration, line 8)
- `TAG_BY_KIND` (lexical_declaration, line 10)
- `tag` (lexical_declaration, line 20)
- `nodes` (lexical_declaration, line 46)
- `open` (lexical_declaration, line 47)

## Uses

- [core/converters/markup.converter.ts](https://banes-lab.com/source/tree/core/converters/markup.converter.ts.md)
- [core/factories/element.factory.ts](https://banes-lab.com/source/tree/core/factories/element.factory.ts.md)
- [presentation/components/link.component.ts](https://banes-lab.com/source/tree/presentation/components/link.component.ts.md)

## Used by

- [presentation/renderers/block.renderer.ts](https://banes-lab.com/source/tree/presentation/renderers/block.renderer.ts.md)
- [presentation/renderers/card.renderer.ts](https://banes-lab.com/source/tree/presentation/renderers/card.renderer.ts.md)
- [presentation/renderers/chapter.renderer.ts](https://banes-lab.com/source/tree/presentation/renderers/chapter.renderer.ts.md)
- [presentation/renderers/document.renderer.ts](https://banes-lab.com/source/tree/presentation/renderers/document.renderer.ts.md)
- [presentation/renderers/folder.renderer.ts](https://banes-lab.com/source/tree/presentation/renderers/folder.renderer.ts.md)
- [presentation/renderers/glossary.block.renderer.ts](https://banes-lab.com/source/tree/presentation/renderers/glossary.block.renderer.ts.md)
- [presentation/renderers/glossary.renderer.ts](https://banes-lab.com/source/tree/presentation/renderers/glossary.renderer.ts.md)
- [presentation/renderers/lesson.renderer.ts](https://banes-lab.com/source/tree/presentation/renderers/lesson.renderer.ts.md)
- [presentation/renderers/markdown.renderer.ts](https://banes-lab.com/source/tree/presentation/renderers/markdown.renderer.ts.md)
- [presentation/renderers/ontology.renderer.ts](https://banes-lab.com/source/tree/presentation/renderers/ontology.renderer.ts.md)
- [presentation/renderers/section.renderer.ts](https://banes-lab.com/source/tree/presentation/renderers/section.renderer.ts.md)
- [presentation/renderers/table.renderer.ts](https://banes-lab.com/source/tree/presentation/renderers/table.renderer.ts.md)
- [presentation/views/home.view.ts](https://banes-lab.com/source/tree/presentation/views/home.view.ts.md)

## Source

```typescript
import { CITE_ATTRIBUTE, CITE_CLASS } from "#configuration/constants/chapter.constants";
import type { ElementTag } from "#types/element.types";
import type { Run } from "#types/markup.types";
import { convertMarkup } from "#core/converters/markup.converter";
import { createElement } from "#core/factories/element.factory";
import { createLink } from "#presentation/components/link.component";

const NO_CLASS = "";

const TAG_BY_KIND: ReadonlyMap<Run["kind"], ElementTag> = new Map([
    ["strong", "strong"],
    ["emphasis", "em"],
    ["code", "code"],
    ["link", "a"],
    ["break", "br"],
    ["cite", "span"],
]);

const renderRun = function renderRun(run: Run): Node {
    const tag = TAG_BY_KIND.get(run.kind);
    if (tag === undefined) {
        return document.createTextNode(run.text);
    }
    if (run.kind === "link" && run.href !== undefined) {
        return createLink(run.href, NO_CLASS, [run.text]);
    }
    if (run.kind === "cite") {
        return createElement("span", {
            attributes: { [CITE_ATTRIBUTE]: run.text },
            className: CITE_CLASS,
            text: run.text,
        });
    }
    return createElement(tag, run.kind === "break" ? {} : { text: run.text });
};

const isEmphasized = function isEmphasized(run: Run): boolean {
    return run.kind === "emphasis" || run.emphasis === true;
};

const renderInside = function renderInside(run: Run): Node {
    return run.kind === "emphasis" ? document.createTextNode(run.text) : renderRun(run);
};

const renderMarkup = function renderMarkup(markup: string): readonly Node[] {
    const nodes: Node[] = [];
    let open: HTMLElement | null = null;
    for (const run of convertMarkup(markup)) {
        if (!isEmphasized(run)) {
            open = null;
            nodes.push(renderRun(run));
            continue;
        }
        if (open === null) {
            open = createElement("em");
            nodes.push(open);
        }
        open.append(renderInside(run));
    }
    return nodes;
};

export const plainText = function plainText(markup: string): string {
    return convertMarkup(markup)
        .map((run) => run.text)
        .join(NO_CLASS);
};

export const fillMarkup = function fillMarkup<T extends Element>(element: T, markup: string): T {
    element.replaceChildren(...renderMarkup(markup));
    return element;
};
```
