# core/loaders/diagram.loader.ts

> 61 lines of code and 15 definitions.

Tree: Site tree
Language: typescript
Layer: infrastructure
Canonical: https://banes-lab.com/anatomy/tree#file-core-loaders-diagram-loader-ts
Source text: https://banes-lab.com/assets/sources/source.6541d27697f6a08bcdf800668120ee43b9032fc1eba7e79306b48e37cf72044b.generated.txt

## Definitions

- `attachStylesheet` (lexical_declaration, line 30)
- `loadDiagram` (lexical_declaration, line 54, exported)
- `fetchMarkup` (lexical_declaration, line 15)
- `styledMarkup` (lexical_declaration, line 44)
- `STYLESHEET_REL` (lexical_declaration, line 8)
- `LOAD_EVENT` (lexical_declaration, line 9)
- `ERROR_EVENT` (lexical_declaration, line 10)
- `held` (lexical_declaration, line 12)
- `styled` (lexical_declaration, line 13)
- `location` (lexical_declaration, line 17)
- `response` (lexical_declaration, line 18)
- `link` (lexical_declaration, line 32)
- `markup` (lexical_declaration, line 45)
- `pending` (lexical_declaration, line 55, exported)
- `loading` (lexical_declaration, line 59, exported)

## Uses

- [core/predicates/resource.predicate.ts](https://banes-lab.com/source/tree/core/predicates/resource.predicate.ts.md)
- [core/reporters/failure.reporter.ts](https://banes-lab.com/source/tree/core/reporters/failure.reporter.ts.md)

## Used by

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

## Source

```typescript
import { DIAGRAM_STYLESHEET, diagramLocation } from "#assets/diagram.assets";
import { DIAGRAM_STYLE_UNAVAILABLE, DIAGRAM_UNAVAILABLE } from "#configuration/strings/report.strings";
import { createElement } from "#core/factories/element.factory";
import { diagramDigest } from "#core/analyzers/diagram.analyzer";
import { isVector } from "#core/predicates/resource.predicate";
import { reportFailure } from "#core/reporters/failure.reporter";

const STYLESHEET_REL = "stylesheet";
const LOAD_EVENT = "load";
const ERROR_EVENT = "error";

const held = new Map<string, Promise<string | null>>();
let styled: Promise<void> | null = null;

const fetchMarkup = async function fetchMarkup(source: string): Promise<string | null> {
    try {
        const location = diagramLocation(await diagramDigest(source));
        const response = await fetch(location);
        if (!isVector(response)) {
            reportFailure(DIAGRAM_UNAVAILABLE, location);
            return null;
        }
        return await response.text();
    } catch (error) {
        reportFailure(DIAGRAM_UNAVAILABLE, error);
        return null;
    }
};

const attachStylesheet = async function attachStylesheet(): Promise<void> {
    return new Promise((settle) => {
        const link = createElement("link", { attributes: { href: DIAGRAM_STYLESHEET, rel: STYLESHEET_REL } });
        link.addEventListener(LOAD_EVENT, () => {
            settle();
        });
        link.addEventListener(ERROR_EVENT, (event) => {
            reportFailure(DIAGRAM_STYLE_UNAVAILABLE, event);
            settle();
        });
        document.head.append(link);
    });
};

const styledMarkup = async function styledMarkup(source: string): Promise<string | null> {
    const markup = await fetchMarkup(source);
    if (markup === null) {
        return null;
    }
    styled ??= attachStylesheet();
    await styled;
    return markup;
};

export const loadDiagram = async function loadDiagram(source: string): Promise<string | null> {
    const pending = held.get(source);
    if (pending !== undefined) {
        return pending;
    }
    const loading = styledMarkup(source).then((markup) => {
        if (markup === null) {
            held.delete(source);
        }
        return markup;
    });
    held.set(source, loading);
    return loading;
};
```
