# core/parsers/diagram.parser.ts

> 58 lines of code and 19 definitions.

Tree: GovLab Docs
Language: typescript
Layer: processing
Canonical: https://banes-lab.com/anatomy/docs#file-docs-core-parsers-diagram-parser-ts
Source text: https://banes-lab.com/source/docs/core/parsers/diagram.parser.ts.txt

Listed in [core/parsers](https://banes-lab.com/api/source/docs/core/parsers.md), after [core/parsers/code.go.parser.ts](https://banes-lab.com/source/docs/core/parsers/code.go.parser.ts.md) and before [core/parsers/export.parser.ts](https://banes-lab.com/source/docs/core/parsers/export.parser.ts.md).

## Definitions

- `mermaidBlocks` (lexical_declaration, line 59, exported)
- `fenceInfoLang` (lexical_declaration, line 9)
- `feed` (method_definition, line 28)
- `openFence` (method_definition, line 45)
- `FENCE_BODY_OFFSET` (lexical_declaration, line 5)
- `MERMAID_LANG` (lexical_declaration, line 6)
- `INLINE_SPACE` (lexical_declaration, line 7)
- `at` (lexical_declaration, line 10)
- `start` (lexical_declaration, line 14)
- `MermaidBlockReader` (class_declaration, line 21)
- `blocks` (public_field_definition, line 22)
- `fence` (public_field_definition, line 23)
- `inMermaid` (public_field_definition, line 24)
- `buffer` (public_field_definition, line 25)
- `startLine` (public_field_definition, line 26)
- `trimmed` (lexical_declaration, line 29)
- `wasOpen` (lexical_declaration, line 30)
- `closeFence` (method_definition, line 51)
- `reader` (lexical_declaration, line 60, exported)

## Contained in

- [core/parsers](https://banes-lab.com/anatomy/docs/folder-docs-core-parsers.md)

## Uses

- [core/parsers/markdown.parser.ts](https://banes-lab.com/source/docs/core/parsers/markdown.parser.ts.md)

## Used by

- [core/analyzers/diagram.analyzer.ts](https://banes-lab.com/source/docs/core/analyzers/diagram.analyzer.ts.md)
- [core/validators/diagram.validator.ts](https://banes-lab.com/source/docs/core/validators/diagram.validator.ts.md)

## Linked from

- [core/analyzers](https://banes-lab.com/anatomy/docs/folder-docs-core-analyzers.md)
- [core/parsers](https://banes-lab.com/anatomy/docs/folder-docs-core-parsers.md)
- [core/validators](https://banes-lab.com/anatomy/docs/folder-docs-core-validators.md)

## Source

```typescript
import { NO_FENCE, splitLines, stepFence } from "#core/parsers/markdown.parser";
import type { Fence } from "#types/markdown.types";
import type { MermaidBlock } from "#types/diagram.types";

const FENCE_BODY_OFFSET = 2;
const MERMAID_LANG = "mermaid";
const INLINE_SPACE: ReadonlySet<string> = new Set([" ", "\t"]);

const fenceInfoLang = function fenceInfoLang(trimmed: string, len: number): string {
    let at = len;
    while (at < trimmed.length && INLINE_SPACE.has(trimmed.charAt(at))) {
        at += 1;
    }
    const start = at;
    while (at < trimmed.length && !INLINE_SPACE.has(trimmed.charAt(at))) {
        at += 1;
    }
    return trimmed.slice(start, at).toLowerCase();
};

class MermaidBlockReader {
    public readonly blocks: MermaidBlock[] = [];
    private fence: Fence = NO_FENCE;
    private inMermaid = false;
    private buffer: string[] = [];
    private startLine = 0;

    public feed(line: string, index: number): void {
        const trimmed = line.trim();
        const wasOpen = this.fence.open;
        this.fence = stepFence(trimmed, this.fence);
        if (!wasOpen && this.fence.open) {
            this.openFence(trimmed, index);
            return;
        }
        if (wasOpen && !this.fence.open) {
            this.closeFence();
            return;
        }
        if (wasOpen && this.inMermaid) {
            this.buffer.push(line);
        }
    }

    private openFence(trimmed: string, index: number): void {
        this.inMermaid = fenceInfoLang(trimmed, this.fence.len) === MERMAID_LANG;
        this.buffer = [];
        this.startLine = index + FENCE_BODY_OFFSET;
    }

    private closeFence(): void {
        if (this.inMermaid) {
            this.blocks.push({ code: this.buffer.join("\n"), startLine: this.startLine });
        }
        this.inMermaid = false;
    }
}

export const mermaidBlocks = function mermaidBlocks(source: string): MermaidBlock[] {
    const reader = new MermaidBlockReader();
    splitLines(source).forEach((line, index) => {
        reader.feed(line, index);
    });
    return reader.blocks;
};
```
