# How the Mermaid Import Parser Handles Grammar Types and Markdown Blocks

> Discover how the Mermaid import parser in cathrynlavery/diagram-design detects grammar types and Markdown blocks, extracting and normalizing content for specialized processing and a sanitized output.

- Repository: [Cathryn Lavery/diagram-design](https://github.com/cathrynlavery/diagram-design)
- Tags: how-to-guide
- Published: 2026-08-15

---

**The Mermaid import parser in `cathrynlavery/diagram-design` detects file formats via extension, extracts fenced code blocks from Markdown, normalizes content by removing front-matter and directives, detects grammar types through lexical scanning, and routes each diagram to specialized parsers that produce a sanitized intermediate representation.**

The parser is implemented in [`skills/diagram-design/scripts/mermaid_extract.py`](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/scripts/mermaid_extract.py) and serves as the entry point for converting Mermaid diagrams into a layout-agnostic intermediate representation (IR). It handles both standalone `.mmd` files and Markdown documents containing fenced Mermaid blocks, applying strict normalization before dispatching to grammar-specific parsers.

## Detecting Source Formats and Markdown Blocks

The parser distinguishes between standalone Mermaid files and Markdown containers through extension-based detection in `load_blocks()` ([source lines 221‑252](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/scripts/mermaid_extract.py#L221-L252)).

### Standalone Files vs. Markdown Containers

The parser accepts three input categories:

- **Standalone Mermaid files**: Extensions `.mmd` or `.mermaid` trigger single-block mode where the entire file content becomes one `SourceBlock` (defined at [lines 80‑84](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/scripts/mermaid_extract.py#L80-L84)).
- **Markdown files**: Extensions `.md`, `.markdown`, `.mkd`, or `.mdown` trigger line-by-line scanning for fenced blocks.

### Fence Extraction Logic

For Markdown inputs, the parser applies a regular expression defined at [lines 35‑42](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/scripts/mermaid_extract.py#L35-L42) to detect fences starting with ` ```mermaid ` or ` ~~~mermaid `. Each matched region becomes a distinct `SourceBlock` with incremental indexing, allowing selective processing via the `--diagram` CLI flag.

## Normalizing Content and Removing Artifacts

Before grammar detection, raw blocks undergo sanitation through `_prepared_lines()` ([source lines 274‑301](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/scripts/mermaid_extract.py#L274-L301)).

### Pre-processing Pipeline

This function returns a list of `(source_line, line_text)` tuples after stripping:

- **Front-matter**: YAML blocks wrapped in `---` that Mermaid treats as configuration directives.
- **Mermaid directives**: Syntax like `%%{…}%%` used for runtime configuration.
- **Comments**: Lines starting with `%%` followed by arbitrary text.

This normalization ensures that grammar detection operates on semantic content rather than metadata or styling instructions.

## Grammar Type Detection and Routing

The parser identifies diagram types through lexical analysis in `_kind_and_direction()` ([source lines 306‑322](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/scripts/mermaid_extract.py#L306-L322)).

### Supported Grammar Types

The scanner examines the first non-empty line of prepared content to classify the diagram:

- **`flowchart` or `graph`**: Kind is set to `"flowchart"` with direction extraction (`TD`, `TB`, `LR`, `RL`, `BT`).
- **`sequenceDiagram`**: Kind is `"sequenceDiagram"` with default left-to-right direction.
- **`stateDiagram-v2`**: Kind is `"stateDiagram-v2"` with default top-down direction.
- **`erDiagram`**: Kind is `"erDiagram"` with default top-down direction.

### Unsupported Grammar Handling

If the detected token belongs to `UNSUPPORTED_KINDS` (including `pie`, `mindmap`, and other syntactically incompatible types), the parser aborts with a clear error message ([source lines 37‑44](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/scripts/mermaid_extract.py#L37-L44)).

## Grammar-Specific Parsing Strategies

After type detection, `parse_block()` ([source lines 447‑459](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/scripts/mermaid_extract.py#L447-L459)) instantiates a `Diagram` object and dispatches to specialized parsers that populate `Diagram.nodes`, `Diagram.edges`, and ancillary structures.

### Flowchart Parsing

`_parse_flowchart()` ([source lines 672‑735](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/scripts/mermaid_extract.py#L672-L735)) handles:
- Node definitions with shape classification
- Subgraph declarations
- Edge connections with style attributes
- Direction statements
- Discarded style directives (tracked but removed from IR)

### Sequence Diagram Parsing

`_parse_sequence()` ([source lines 742‑808](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/scripts/mermaid_extract.py#L742-L808)) processes:
- Participant declarations
- Fragment blocks (`alt`, `opt`, `loop`, `par`)
- Note placements
- Message edges with activation indicators

### State Diagram Parsing

`_parse_state()` ([source lines 813‑855](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/scripts/mermaid_extract.py#L813-L855)) extracts:
- Simple state nodes
- Composite state hierarchies
- Direction hints within state blocks
- Transition edges with event triggers

### ER Diagram Parsing

`_parse_er()` ([source lines 894‑943](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/scripts/mermaid_extract.py#L894-L943)) parses:
- Entity declarations with field lists
- Relationship edges respecting cardinality syntax (`||--o{`, etc.)
- Attribute type annotations

## Security Sanitization and Trust Boundaries

The parser enforces a strict trust boundary across all grammar types to prevent injection of non-semantic content.

### Label Sanitization

`clean_label()` ([source lines 87‑103](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/scripts/mermaid_extract.py#L87-L103)) strips:
- Markdown styling syntax (italics, bold)
- HTML entities and tags
- Class attachments (`:::class` suffixes)

### Non-Semantic Directive Removal

`_discard_nonsemantic()` ([source lines 560‑668](https://github.com/cathrynlavery/diagram-design/blob/main/skills/diagram-design/scripts/mermaid_extract.py#L560-L668)) counts and removes:
- Click handlers and JavaScript callbacks
- Style directives that affect rendering but not structure
- CSS class assignments

## Command-Line Usage and Output Formats

The parser exposes three primary workflows via CLI:

### Processing Standalone Mermaid Files

```bash
python3 skills/diagram-design/scripts/mermaid_extract.py \
  examples/sample-flowchart.mmd \
  --json

```

### Extracting from Markdown with Multiple Diagrams

```bash
python3 skills/diagram-design/scripts/mermaid_extract.py \
  docs/README.md \
  --diagram all \
  --max-rows 20

```

### Generating Human-Readable Digests

```bash
python3 skills/diagram-design/scripts/mermaid_extract.py \
  docs/README.md

```

The `--diagram` parameter accepts an integer index (for specific blocks) or `all` (for batch processing). Output formats include:
- **JSON**: Machine-readable IR via `to_json()`
- **Markdown digest**: Human summary via `digest()` showing node counts, directions, and cycle detection

## Summary

- The **Mermaid import parser** resides in `skills/diagram-design/scripts/mermaid_extract.py` and processes both `.mmd` files and Markdown documents.
- **Format detection** occurs in `load_blocks()`, using file extensions to determine whether to treat content as a single block or scan for fenced regions.
- **Content normalization** via `_prepared_lines()` removes front-matter, directives, and comments before grammar analysis.
- **Grammar detection** in `_kind_and_direction()` supports `flowchart`, `sequenceDiagram`, `stateDiagram-v2`, and `erDiagram`, explicitly rejecting unsupported types like `pie` or `mindmap`.
- **Specialized parsers** handle each grammar type's unique syntax, building a normalized IR with sanitized labels and discard tracking.
- **Security measures** include `clean_label()` for content scrubbing and `_discard_nonsemantic()` for removing executable directives.

## Frequently Asked Questions

### How does the parser distinguish between Markdown and standalone Mermaid files?

The parser examines file extensions in `load_blocks()`. Files ending in `.mmd` or `.mermaid` are treated as single raw blocks, while `.md`, `.markdown`, `.mkd`, or `.mdown` extensions trigger fenced-code-block scanning using regex patterns matching ` ```mermaid ` or ` ~~~mermaid ` delimiters.

### What happens to unsupported diagram types like pie charts or mindmaps?

When `_kind_and_direction()` encounters a token listed in `UNSUPPORTED_KINDS` (such as `pie` or `mindmap`), the parser immediately aborts with a descriptive error. This prevents partial parsing of grammars that lack specialized handlers in the current implementation.

### Can the parser handle multiple Mermaid diagrams in a single Markdown file?

Yes. The `load_blocks()` function extracts each fenced Mermaid region into separate `SourceBlock` instances with incremental indices. Users can process specific diagrams using `--diagram N` (where N is the block index) or process all diagrams using `--diagram all`.

### How does the parser ensure extracted content is safe for further processing?

The parser applies `clean_label()` to strip Markdown formatting, HTML entities, and CSS class attachments from all labels. Additionally, `_discard_nonsemantic()` counts and removes click handlers, style directives, and other presentation-layer metadata that could execute code or affect layout calculations.