How the Mermaid Import Parser Handles Grammar Types and Markdown Blocks

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 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).

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).
  • 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 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).

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).

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).

Grammar-Specific Parsing Strategies

After type detection, parse_block() (source lines 447‑459) 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) 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) 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) 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) 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) strips:

  • Markdown styling syntax (italics, bold)
  • HTML entities and tags
  • Class attachments (:::class suffixes)

Non-Semantic Directive Removal

_discard_nonsemantic() (source lines 560‑668) 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

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

Extracting from Markdown with Multiple Diagrams

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

Generating Human-Readable Digests

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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →