Beautiful Mermaid

Mermaid Rendering, made beautiful.

An open source library for rendering diagrams, designed for the age of AI: beautiful-mermaid. Ultra-fast, fully themeable, and outputs to both SVG and ASCII.
Built by the team at Craft — because diagrams deserve great design too.

npm install GitHub

Rendering 150 samples…

Samples rendered client-side in real time
Early preview — actively evolving

Samples

XSS Test 1 - formatDescription Bypass

Testing backtick injection: - if you see an alert, XSS works!

graph TD
  A[Start] --> B[Test]
Rendering…

XSS Test 2 - SVG Node Label

Testing SVG node label escaping

graph TD
  A[<script>alert("XSS-VALIDATION-TOKEN-2")</script>] --> B[Normal]
Rendering…

XSS Test 3 - SVG Event Handler

Testing SVG event handler injection

graph TD
  A[<img src=x onerror=alert("XSS-VALIDATION-TOKEN-3")>] --> B[Test]
Rendering…

XSS Test 4 - Style Directive Injection

Testing style directive attribute injection - CRITICAL VULNERABILITY

graph TD
  A[Vulnerable Node] --> B[Target]
  style A fill:#f00" onload="alert('XSS-STYLE-INJECTION')
Rendering…

XSS Test 5 - Style Directive with SVG Event

Testing style directive with SVG-specific event handler

graph TD
  A[Test] --> B[Node]
  style A fill:#ff0000" onclick="alert('XSS-CLICK-TEST')
Rendering…

Simple Flow

Basic linear flow with three nodes connected by solid arrows.

graph TD
  A[Start] --> B[Process] --> C[End]
Rendering…

Original Node Shapes

Rectangle, rounded, diamond, stadium, and circle.

graph LR
  A[Rectangle] --> B(Rounded)
  B --> C{Diamond}
  C --> D([Stadium])
  D --> E((Circle))
Rendering…

Batch 1 Shapes

Subroutine [[text]], double circle (((text))), and hexagon {{text}}.

graph LR
  A[[Subroutine]] --> B(((Double Circle)))
  B --> C{{Hexagon}}
Rendering…

Batch 2 Shapes

Cylinder [(text)], asymmetric >text], trapezoid [/text\], and inverse trapezoid [\text/].

graph LR
  A[(Database)] --> B>Flag Shape]
  B --> C[/Wider Bottom\]
  C --> D[\Wider Top/]
Rendering…

All 12 Flowchart Shapes

Every supported flowchart shape in a single diagram.

graph LR
  A[Rectangle] --> B(Rounded)
  B --> C{Diamond}
  C --> D([Stadium])
  D --> E((Circle))
  E --> F[[Subroutine]]
  F --> G(((Double Circle)))
  G --> H{{Hexagon}}
  H --> I[(Database)]
  I --> J>Flag]
  J --> K[/Trapezoid\]
  K --> L[\Inverse Trap/]
Rendering…

All Edge Styles

Solid, dotted, and thick arrows with labels.

graph TD
  A[Source] -->|solid| B[Target 1]
  A -.->|dotted| C[Target 2]
  A ==>|thick| D[Target 3]
Rendering…

No-Arrow Edges

Lines without arrowheads: solid ---, dotted -.-, thick ===.

graph TD
  A[Node 1] ---|related| B[Node 2]
  B -.- C[Node 3]
  C === D[Node 4]
Rendering…

Bidirectional Arrows

Arrows in both directions: <-->, <-.->, <==>.

graph LR
  A[Client] <-->|sync| B[Server]
  B <-.->|heartbeat| C[Monitor]
  C <==>|data| D[Storage]
Rendering…

Parallel Links (&)

Using & to create multiple edges from/to groups of nodes.

graph TD
  A[Input] & B[Config] --> C[Processor]
  C --> D[Output] & E[Log]
Rendering…

Chained Edges

A long chain of nodes demonstrating edge chaining syntax.

graph LR
  A[Step 1] --> B[Step 2] --> C[Step 3] --> D[Step 4] --> E[Step 5]
Rendering…

Direction: Left-Right (LR)

Horizontal layout flowing left to right.

graph LR
  A[Input] --> B[Transform] --> C[Output]
Rendering…

Direction: Bottom-Top (BT)

Vertical layout flowing from bottom to top.

graph BT
  A[Foundation] --> B[Layer 2] --> C[Top]
Rendering…

Subgraphs

Grouped nodes inside labeled subgraph containers.

graph TD
  subgraph Frontend
    A[React App] --> B[State Manager]
  end
  subgraph Backend
    C[API Server] --> D[Database]
  end
  B --> C
Rendering…

Nested Subgraphs

Subgraphs inside subgraphs for hierarchical grouping.

graph TD
  subgraph Cloud
    subgraph us-east [US East Region]
      A[Web Server] --> B[App Server]
    end
    subgraph us-west [US West Region]
      C[Web Server] --> D[App Server]
    end
  end
  E[Load Balancer] --> A
  E --> C
Rendering…

Subgraph Direction Override

Using direction LR inside a subgraph while the outer graph flows TD.

graph TD
  subgraph pipeline [Processing Pipeline]
    direction LR
    A[Input] --> B[Parse] --> C[Transform] --> D[Output]
  end
  E[Source] --> A
  D --> F[Sink]
Rendering…

::: Class Shorthand

Assigning classes with ::: syntax directly on node definitions.

graph TD
  A[Normal]:::default --> B[Highlighted]:::highlight --> C[Error]:::error
  classDef default fill:#f4f4f5,stroke:#a1a1aa
  classDef highlight fill:#fbbf24,stroke:#d97706
  classDef error fill:#ef4444,stroke:#dc2626
Rendering…

Inline Style Overrides

Using style statements to override node fill and stroke colors.

graph TD
  A[Default] --> B[Custom Colors] --> C[Another Custom]
  style B fill:#3b82f6,stroke:#1d4ed8,color:#ffffff
  style C fill:#10b981,stroke:#059669
Rendering…

CI/CD Pipeline

A realistic CI/CD pipeline with decision points, feedback loops, and deployment stages.

graph TD
  subgraph ci [CI Pipeline]
    A[Push Code] --> B{Tests Pass?}
    B -->|Yes| C[Build Image]
    B -->|No| D[Fix & Retry]
    D -.-> A
  end
  C --> E([Deploy Staging])
  E --> F{QA Approved?}
  F -->|Yes| G((Production))
  F -->|No| D
Rendering…

System Architecture

A microservices architecture with multiple services and data stores.

graph LR
  subgraph clients [Client Layer]
    A([Web App]) --> B[API Gateway]
    C([Mobile App]) --> B
  end
  subgraph services [Service Layer]
    B --> D[Auth Service]
    B --> E[User Service]
    B --> F[Order Service]
  end
  subgraph data [Data Layer]
    D --> G[(Auth DB)]
    E --> H[(User DB)]
    F --> I[(Order DB)]
    F --> J([Message Queue])
  end
Rendering…

Decision Tree

A branching decision flowchart with multiple outcomes.

graph TD
  A{Is it raining?} -->|Yes| B{Have umbrella?}
  A -->|No| C([Go outside])
  B -->|Yes| D([Go with umbrella])
  B -->|No| E{Is it heavy?}
  E -->|Yes| F([Stay inside])
  E -->|No| G([Run for it])
Rendering…

Git Branching Workflow

A git flow showing feature branches, PRs, and release cycle.

graph LR
  A[main] --> B[develop]
  B --> C[feature/auth]
  B --> D[feature/ui]
  C --> E{PR Review}
  D --> E
  E -->|approved| B
  B --> F[release/1.0]
  F --> G{Tests?}
  G -->|pass| A
  G -->|fail| F
Rendering…

Basic State Diagram

A simple stateDiagram-v2 with start/end pseudostates and transitions.

stateDiagram-v2
  [*] --> Idle
  Idle --> Active : start
  Active --> Idle : cancel
  Active --> Done : complete
  Done --> [*]
Rendering…

State: Composite States

Nested composite states with inner transitions.

stateDiagram-v2
  [*] --> Idle
  Idle --> Processing : submit
  state Processing {
    parse --> validate
    validate --> execute
  }
  Processing --> Complete : done
  Processing --> Error : fail
  Error --> Idle : retry
  Complete --> [*]
Rendering…

State: Connection Lifecycle

TCP-like connection state machine with multiple states.

stateDiagram-v2
  [*] --> Closed
  Closed --> Connecting : connect
  Connecting --> Connected : success
  Connecting --> Closed : timeout
  Connected --> Disconnecting : close
  Connected --> Reconnecting : error
  Reconnecting --> Connected : success
  Reconnecting --> Closed : max_retries
  Disconnecting --> Closed : done
  Closed --> [*]
Rendering…

Sequence: Basic Messages

Simple request/response between two participants.

sequenceDiagram
  Alice->>Bob: Hello Bob!
  Bob-->>Alice: Hi Alice!
Rendering…

Sequence: Participant Aliases

Using participant ... as ... for compact diagram IDs with readable labels.

sequenceDiagram
  participant A as Alice
  participant B as Bob
  participant C as Charlie
  A->>B: Hello
  B->>C: Forward
  C-->>A: Reply
Rendering…

Sequence: Actor Stick Figures

Using actor instead of participant renders stick figures instead of boxes.

sequenceDiagram
  actor U as User
  participant S as System
  participant DB as Database
  U->>S: Click button
  S->>DB: Query
  DB-->>S: Results
  S-->>U: Display
Rendering…

Sequence: Arrow Types

All arrow types: solid ->> and dashed -->> with filled arrowheads, open arrows -) .

sequenceDiagram
  A->>B: Solid arrow (sync)
  B-->>A: Dashed arrow (return)
  A-)B: Open arrow (async)
  B--)A: Open dashed arrow
Rendering…

Sequence: Activation Boxes

Using + and - to show when participants are active.

sequenceDiagram
  participant C as Client
  participant S as Server
  C->>+S: Request
  S->>+S: Process
  S->>-S: Done
  S-->>-C: Response
Rendering…

Sequence: Self-Messages

A participant sending a message to itself (displayed as a loop arrow).

sequenceDiagram
  participant S as Server
  S->>S: Internal process
  S->>S: Validate
  S-->>S: Log
Rendering…

Sequence: Loop Block

A loop construct wrapping repeated message exchanges.

sequenceDiagram
  participant C as Client
  participant S as Server
  C->>S: Connect
  loop Every 30s
    C->>S: Heartbeat
    S-->>C: Ack
  end
  C->>S: Disconnect
Rendering…

Sequence: Alt/Else Block

Conditional branching with alt (if) and else blocks.

sequenceDiagram
  participant C as Client
  participant S as Server
  C->>S: Login
  alt Valid credentials
    S-->>C: 200 OK
  else Invalid
    S-->>C: 401 Unauthorized
  else Account locked
    S-->>C: 403 Forbidden
  end
Rendering…

Sequence: Opt Block

Optional block — executes only if condition is met.

sequenceDiagram
  participant A as App
  participant C as Cache
  participant DB as Database
  A->>C: Get data
  C-->>A: Cache miss
  opt Cache miss
    A->>DB: Query
    DB-->>A: Results
    A->>C: Store in cache
  end
Rendering…

Sequence: Par Block

Parallel execution with par/and constructs.

sequenceDiagram
  participant C as Client
  participant A as AuthService
  participant U as UserService
  participant O as OrderService
  C->>A: Authenticate
  par Fetch user data
    A->>U: Get profile
  and Fetch orders
    A->>O: Get orders
  end
  A-->>C: Combined response
Rendering…

Sequence: Critical Block

Critical section that must complete atomically.

sequenceDiagram
  participant A as App
  participant DB as Database
  A->>DB: BEGIN
  critical Transaction
    A->>DB: UPDATE accounts
    A->>DB: INSERT log
  end
  A->>DB: COMMIT
Rendering…

Sequence: Notes (Right/Left/Over)

Notes positioned to the right, left, or over participants.

sequenceDiagram
  participant A as Alice
  participant B as Bob
  Note left of A: Alice prepares
  A->>B: Hello
  Note right of B: Bob thinks
  B-->>A: Reply
  Note over A,B: Conversation complete
Rendering…

Sequence: OAuth 2.0 Flow

Full OAuth 2.0 authorization code flow with token exchange.

sequenceDiagram
  actor U as User
  participant App as Client App
  participant Auth as Auth Server
  participant API as Resource API
  U->>App: Click Login
  App->>Auth: Authorization request
  Auth->>U: Login page
  U->>Auth: Credentials
  Auth-->>App: Authorization code
  App->>Auth: Exchange code for token
  Auth-->>App: Access token
  App->>API: Request + token
  API-->>App: Protected resource
  App-->>U: Display data
Rendering…

Sequence: Database Transaction

Multi-step database transaction with rollback handling.

sequenceDiagram
  participant C as Client
  participant S as Server
  participant DB as Database
  C->>S: POST /transfer
  S->>DB: BEGIN
  S->>DB: Debit account A
  alt Success
    S->>DB: Credit account B
    S->>DB: INSERT audit_log
    S->>DB: COMMIT
    S-->>C: 200 OK
  else Insufficient funds
    S->>DB: ROLLBACK
    S-->>C: 400 Bad Request
  end
Rendering…

Sequence: Microservice Orchestration

Complex multi-service flow with parallel calls and error handling.

sequenceDiagram
  participant G as Gateway
  participant A as Auth
  participant U as Users
  participant O as Orders
  participant N as Notify
  G->>A: Validate token
  A-->>G: Valid
  par Fetch data
    G->>U: Get user
    U-->>G: User data
  and
    G->>O: Get orders
    O-->>G: Order list
  end
  G->>N: Send notification
  N-->>G: Queued
  Note over G: Aggregate response
Rendering…

Class: Basic Class

A single class with attributes and methods, rendered as a 3-compartment box.

classDiagram
  class Animal {
    +String name
    +int age
    +eat() void
    +sleep() void
  }
Rendering…

Class: Visibility Markers

All four visibility levels: + (public), - (private), # (protected), ~ (package).

classDiagram
  class User {
    +String name
    -String password
    #int internalId
    ~String packageField
    +login() bool
    -hashPassword() String
    #validate() void
    ~notify() void
  }
Rendering…

Class: Interface Annotation

Using <> annotation above the class name.

classDiagram
  class Serializable {
    <<interface>>
    +serialize() String
    +deserialize(data) void
  }
Rendering…

Class: Abstract Annotation

Using <> annotation for abstract classes.

classDiagram
  class Shape {
    <<abstract>>
    +String color
    +area() double
    +draw() void
  }
Rendering…

Class: Enum Annotation

Using <> annotation for enum types.

classDiagram
  class Status {
    <<enumeration>>
    ACTIVE
    INACTIVE
    PENDING
    DELETED
  }
Rendering…

Class: Inheritance (<|--)

Inheritance relationship rendered with a hollow triangle marker.

classDiagram
  class Animal {
    +String name
    +eat() void
  }
  class Dog {
    +String breed
    +bark() void
  }
  class Cat {
    +bool isIndoor
    +meow() void
  }
  Animal <|-- Dog
  Animal <|-- Cat
Rendering…

Class: Composition (*--)

Composition — "owns" relationship with filled diamond marker.

classDiagram
  class Car {
    +String model
    +start() void
  }
  class Engine {
    +int horsepower
    +rev() void
  }
  Car *-- Engine
Rendering…

Class: Aggregation (o--)

Aggregation — "has" relationship with hollow diamond marker.

classDiagram
  class University {
    +String name
  }
  class Department {
    +String faculty
  }
  University o-- Department
Rendering…

Class: Association (-->)

Basic association — simple directed arrow.

classDiagram
  class Customer {
    +String name
  }
  class Order {
    +int orderId
  }
  Customer --> Order
Rendering…

Class: Dependency (..>)

Dependency — dashed line with open arrow.

classDiagram
  class Service {
    +process() void
  }
  class Repository {
    +find() Object
  }
  Service ..> Repository
Rendering…

Class: Realization (..|>)

Realization — dashed line with hollow triangle (implements interface).

classDiagram
  class Flyable {
    <<interface>>
    +fly() void
  }
  class Bird {
    +fly() void
    +sing() void
  }
  Bird ..|> Flyable
Rendering…

Class: All 6 Relationship Types

Every relationship type in a single diagram for comparison.

classDiagram
  A <|-- B : inheritance
  C *-- D : composition
  E o-- F : aggregation
  G --> H : association
  I ..> J : dependency
  K ..|> L : realization
Rendering…

Class: Relationship Labels

Labeled relationships between classes with descriptive text.

classDiagram
  class Teacher {
    +String name
  }
  class Student {
    +String name
  }
  class Course {
    +String title
  }
  Teacher --> Course : teaches
  Student --> Course : enrolled in
Rendering…

Class: Design Pattern — Observer

The Observer (publish-subscribe) design pattern with interface + concrete implementations.

classDiagram
  class Subject {
    <<interface>>
    +attach(Observer) void
    +detach(Observer) void
    +notify() void
  }
  class Observer {
    <<interface>>
    +update() void
  }
  class EventEmitter {
    -List~Observer~ observers
    +attach(Observer) void
    +detach(Observer) void
    +notify() void
  }
  class Logger {
    +update() void
  }
  class Alerter {
    +update() void
  }
  Subject <|.. EventEmitter
  Observer <|.. Logger
  Observer <|.. Alerter
  EventEmitter --> Observer
Rendering…

Class: MVC Architecture

Model-View-Controller pattern showing relationships between layers.

classDiagram
  class Model {
    -data Map
    +getData() Map
    +setData(key, val) void
    +notify() void
  }
  class View {
    -model Model
    +render() void
    +update() void
  }
  class Controller {
    -model Model
    -view View
    +handleInput(event) void
    +updateModel(data) void
  }
  Controller --> Model : updates
  Controller --> View : refreshes
  View --> Model : reads
  Model ..> View : notifies
Rendering…

Class: Full Hierarchy

A complete class hierarchy with abstract base, interfaces, and concrete classes.

classDiagram
  class Animal {
    <<abstract>>
    +String name
    +int age
    +eat() void
    +sleep() void
  }
  class Mammal {
    +bool warmBlooded
    +nurse() void
  }
  class Bird {
    +bool canFly
    +layEggs() void
  }
  class Dog {
    +String breed
    +bark() void
  }
  class Cat {
    +bool isIndoor
    +purr() void
  }
  class Parrot {
    +String vocabulary
    +speak() void
  }
  Animal <|-- Mammal
  Animal <|-- Bird
  Mammal <|-- Dog
  Mammal <|-- Cat
  Bird <|-- Parrot
Rendering…

ER: Basic Relationship

A simple one-to-many relationship between two entities.

erDiagram
  CUSTOMER ||--o{ ORDER : places
Rendering…

ER: Entity with Attributes

An entity with typed attributes and PK/FK/UK key badges.

erDiagram
  CUSTOMER {
    int id PK
    string name
    string email UK
    date created_at
  }
Rendering…

ER: Attribute Keys (PK, FK, UK)

All three key constraint types rendered as badges.

erDiagram
  ORDER {
    int id PK
    int customer_id FK
    string invoice_number UK
    decimal total
    date order_date
    string status
  }
Rendering…

ER: Exactly One to Exactly One (||--||)

One-to-one mandatory relationship.

erDiagram
  PERSON ||--|| PASSPORT : has
Rendering…

ER: Exactly One to Zero-or-Many (||--o{)

Classic one-to-many optional relationship (crow's foot).

erDiagram
  CUSTOMER ||--o{ ORDER : places
Rendering…

ER: Zero-or-One to One-or-Many (|o--|{)

Optional on one side, at-least-one on the other.

erDiagram
  SUPERVISOR |o--|{ EMPLOYEE : manages
Rendering…

ER: One-or-More to Zero-or-Many (}|--o{)

At-least-one to zero-or-many relationship.

erDiagram
  TEACHER }|--o{ COURSE : teaches
Rendering…

ER: All Cardinality Types

Every cardinality combination in one diagram.

erDiagram
  A ||--|| B : one-to-one
  C ||--o{ D : one-to-many
  E |o--|{ F : opt-to-many
  G }|--o{ H : many-to-many
Rendering…

ER: Identifying (Solid) Relationship

Solid line indicating an identifying relationship (child depends on parent for identity).

erDiagram
  ORDER ||--|{ LINE_ITEM : contains
Rendering…

ER: Non-Identifying (Dashed) Relationship

Dashed line indicating a non-identifying relationship.

erDiagram
  USER ||..o{ LOG_ENTRY : generates
  USER ||..o{ SESSION : opens
Rendering…

ER: Mixed Identifying & Non-Identifying

Both solid and dashed lines in the same diagram.

erDiagram
  ORDER ||--|{ LINE_ITEM : contains
  ORDER ||..o{ SHIPMENT : ships-via
  PRODUCT ||--o{ LINE_ITEM : includes
  PRODUCT ||..o{ REVIEW : receives
Rendering…

ER: E-Commerce Schema

Full e-commerce database schema with customers, orders, products, and line items.

erDiagram
  CUSTOMER {
    int id PK
    string name
    string email UK
  }
  ORDER {
    int id PK
    date created
    int customer_id FK
  }
  PRODUCT {
    int id PK
    string name
    float price
  }
  LINE_ITEM {
    int id PK
    int order_id FK
    int product_id FK
    int quantity
  }
  CUSTOMER ||--o{ ORDER : places
  ORDER ||--|{ LINE_ITEM : contains
  PRODUCT ||--o{ LINE_ITEM : includes
Rendering…

ER: Blog Platform Schema

Blog system with users, posts, comments, and tags.

erDiagram
  USER {
    int id PK
    string username UK
    string email UK
    date joined
  }
  POST {
    int id PK
    string title
    text content
    int author_id FK
    date published
  }
  COMMENT {
    int id PK
    text body
    int post_id FK
    int user_id FK
    date created
  }
  TAG {
    int id PK
    string name UK
  }
  USER ||--o{ POST : writes
  USER ||--o{ COMMENT : authors
  POST ||--o{ COMMENT : has
  POST }|--o{ TAG : tagged-with
Rendering…

ER: School Management Schema

School system with students, teachers, courses, and enrollments.

erDiagram
  STUDENT {
    int id PK
    string name
    date dob
    string grade
  }
  TEACHER {
    int id PK
    string name
    string department
  }
  COURSE {
    int id PK
    string title
    int teacher_id FK
    int credits
  }
  ENROLLMENT {
    int id PK
    int student_id FK
    int course_id FK
    string semester
    float grade
  }
  TEACHER ||--o{ COURSE : teaches
  STUDENT ||--o{ ENROLLMENT : enrolled
  COURSE ||--o{ ENROLLMENT : has
Rendering…
] --> B[Normal]","category":"Flowchart","options":{}},{"title":"XSS Test 3 - SVG Event Handler","description":"Testing SVG event handler injection","source":"graph TD\n A[] --> B[Test]","category":"Flowchart","options":{}},{"title":"XSS Test 4 - Style Directive Injection","description":"Testing style directive attribute injection - CRITICAL VULNERABILITY","source":"graph TD\n A[Vulnerable Node] --> B[Target]\n style A fill:#f00\" onload=\"alert('XSS-STYLE-INJECTION')","category":"Flowchart","options":{}},{"title":"XSS Test 5 - Style Directive with SVG Event","description":"Testing style directive with SVG-specific event handler","source":"graph TD\n A[Test] --> B[Node]\n style A fill:#ff0000\" onclick=\"alert('XSS-CLICK-TEST')","category":"Flowchart","options":{}},{"title":"Beautiful Mermaid","description":"Mermaid rendering, made beautiful.","source":"stateDiagram-v2\n direction LR\n [*] --> Input\n Input --> Parse: DSL\n Parse --> Layout: AST\n Layout --> SVG: Vector\n Layout --> ASCII: Text\n SVG --> Theme\n ASCII --> Theme\n Theme --> Output\n Output --> [*]","category":"Hero","options":{"transparent":true}},{"title":"Simple Flow","description":"Basic linear flow with three nodes connected by solid arrows.","source":"graph TD\n A[Start] --> B[Process] --> C[End]","category":"Flowchart","options":{}},{"title":"Original Node Shapes","description":"Rectangle, rounded, diamond, stadium, and circle.","source":"graph LR\n A[Rectangle] --> B(Rounded)\n B --> C{Diamond}\n C --> D([Stadium])\n D --> E((Circle))","category":"Flowchart","options":{}},{"title":"Batch 1 Shapes","description":"Subroutine `[[text]]`, double circle `(((text)))`, and hexagon `{{text}}`.","source":"graph LR\n A[[Subroutine]] --> B(((Double Circle)))\n B --> C{{Hexagon}}","category":"Flowchart","options":{}},{"title":"Batch 2 Shapes","description":"Cylinder `[(text)]`, asymmetric `>text]`, trapezoid `[/text\\]`, and inverse trapezoid `[\\text/]`.","source":"graph LR\n A[(Database)] --> B>Flag Shape]\n B --> C[/Wider Bottom\\]\n C --> D[\\Wider Top/]","category":"Flowchart","options":{}},{"title":"All 12 Flowchart Shapes","description":"Every supported flowchart shape in a single diagram.","source":"graph LR\n A[Rectangle] --> B(Rounded)\n B --> C{Diamond}\n C --> D([Stadium])\n D --> E((Circle))\n E --> F[[Subroutine]]\n F --> G(((Double Circle)))\n G --> H{{Hexagon}}\n H --> I[(Database)]\n I --> J>Flag]\n J --> K[/Trapezoid\\]\n K --> L[\\Inverse Trap/]","category":"Flowchart","options":{}},{"title":"All Edge Styles","description":"Solid, dotted, and thick arrows with labels.","source":"graph TD\n A[Source] -->|solid| B[Target 1]\n A -.->|dotted| C[Target 2]\n A ==>|thick| D[Target 3]","category":"Flowchart","options":{}},{"title":"No-Arrow Edges","description":"Lines without arrowheads: solid `---`, dotted `-.-`, thick `===`.","source":"graph TD\n A[Node 1] ---|related| B[Node 2]\n B -.- C[Node 3]\n C === D[Node 4]","category":"Flowchart","options":{}},{"title":"Bidirectional Arrows","description":"Arrows in both directions: `<-->`, `<-.->`, `<==>`.","source":"graph LR\n A[Client] <-->|sync| B[Server]\n B <-.->|heartbeat| C[Monitor]\n C <==>|data| D[Storage]","category":"Flowchart","options":{}},{"title":"Parallel Links (&)","description":"Using `&` to create multiple edges from/to groups of nodes.","source":"graph TD\n A[Input] & B[Config] --> C[Processor]\n C --> D[Output] & E[Log]","category":"Flowchart","options":{}},{"title":"Chained Edges","description":"A long chain of nodes demonstrating edge chaining syntax.","source":"graph LR\n A[Step 1] --> B[Step 2] --> C[Step 3] --> D[Step 4] --> E[Step 5]","category":"Flowchart","options":{}},{"title":"Direction: Left-Right (LR)","description":"Horizontal layout flowing left to right.","source":"graph LR\n A[Input] --> B[Transform] --> C[Output]","category":"Flowchart","options":{}},{"title":"Direction: Bottom-Top (BT)","description":"Vertical layout flowing from bottom to top.","source":"graph BT\n A[Foundation] --> B[Layer 2] --> C[Top]","category":"Flowchart","options":{}},{"title":"Subgraphs","description":"Grouped nodes inside labeled subgraph containers.","source":"graph TD\n subgraph Frontend\n A[React App] --> B[State Manager]\n end\n subgraph Backend\n C[API Server] --> D[Database]\n end\n B --> C","category":"Flowchart","options":{}},{"title":"Nested Subgraphs","description":"Subgraphs inside subgraphs for hierarchical grouping.","source":"graph TD\n subgraph Cloud\n subgraph us-east [US East Region]\n A[Web Server] --> B[App Server]\n end\n subgraph us-west [US West Region]\n C[Web Server] --> D[App Server]\n end\n end\n E[Load Balancer] --> A\n E --> C","category":"Flowchart","options":{}},{"title":"Subgraph Direction Override","description":"Using `direction LR` inside a subgraph while the outer graph flows TD.","source":"graph TD\n subgraph pipeline [Processing Pipeline]\n direction LR\n A[Input] --> B[Parse] --> C[Transform] --> D[Output]\n end\n E[Source] --> A\n D --> F[Sink]","category":"Flowchart","options":{}},{"title":"::: Class Shorthand","description":"Assigning classes with `:::` syntax directly on node definitions.","source":"graph TD\n A[Normal]:::default --> B[Highlighted]:::highlight --> C[Error]:::error\n classDef default fill:#f4f4f5,stroke:#a1a1aa\n classDef highlight fill:#fbbf24,stroke:#d97706\n classDef error fill:#ef4444,stroke:#dc2626","category":"Flowchart","options":{}},{"title":"Inline Style Overrides","description":"Using `style` statements to override node fill and stroke colors.","source":"graph TD\n A[Default] --> B[Custom Colors] --> C[Another Custom]\n style B fill:#3b82f6,stroke:#1d4ed8,color:#ffffff\n style C fill:#10b981,stroke:#059669","category":"Flowchart","options":{}},{"title":"CI/CD Pipeline","description":"A realistic CI/CD pipeline with decision points, feedback loops, and deployment stages.","source":"graph TD\n subgraph ci [CI Pipeline]\n A[Push Code] --> B{Tests Pass?}\n B -->|Yes| C[Build Image]\n B -->|No| D[Fix & Retry]\n D -.-> A\n end\n C --> E([Deploy Staging])\n E --> F{QA Approved?}\n F -->|Yes| G((Production))\n F -->|No| D","category":"Flowchart","options":{}},{"title":"System Architecture","description":"A microservices architecture with multiple services and data stores.","source":"graph LR\n subgraph clients [Client Layer]\n A([Web App]) --> B[API Gateway]\n C([Mobile App]) --> B\n end\n subgraph services [Service Layer]\n B --> D[Auth Service]\n B --> E[User Service]\n B --> F[Order Service]\n end\n subgraph data [Data Layer]\n D --> G[(Auth DB)]\n E --> H[(User DB)]\n F --> I[(Order DB)]\n F --> J([Message Queue])\n end","category":"Flowchart","options":{}},{"title":"Decision Tree","description":"A branching decision flowchart with multiple outcomes.","source":"graph TD\n A{Is it raining?} -->|Yes| B{Have umbrella?}\n A -->|No| C([Go outside])\n B -->|Yes| D([Go with umbrella])\n B -->|No| E{Is it heavy?}\n E -->|Yes| F([Stay inside])\n E -->|No| G([Run for it])","category":"Flowchart","options":{}},{"title":"Git Branching Workflow","description":"A git flow showing feature branches, PRs, and release cycle.","source":"graph LR\n A[main] --> B[develop]\n B --> C[feature/auth]\n B --> D[feature/ui]\n C --> E{PR Review}\n D --> E\n E -->|approved| B\n B --> F[release/1.0]\n F --> G{Tests?}\n G -->|pass| A\n G -->|fail| F","category":"Flowchart","options":{}},{"title":"Basic State Diagram","description":"A simple `stateDiagram-v2` with start/end pseudostates and transitions.","source":"stateDiagram-v2\n [*] --> Idle\n Idle --> Active : start\n Active --> Idle : cancel\n Active --> Done : complete\n Done --> [*]","category":"State","options":{}},{"title":"State: Composite States","description":"Nested composite states with inner transitions.","source":"stateDiagram-v2\n [*] --> Idle\n Idle --> Processing : submit\n state Processing {\n parse --> validate\n validate --> execute\n }\n Processing --> Complete : done\n Processing --> Error : fail\n Error --> Idle : retry\n Complete --> [*]","category":"State","options":{}},{"title":"State: Connection Lifecycle","description":"TCP-like connection state machine with multiple states.","source":"stateDiagram-v2\n [*] --> Closed\n Closed --> Connecting : connect\n Connecting --> Connected : success\n Connecting --> Closed : timeout\n Connected --> Disconnecting : close\n Connected --> Reconnecting : error\n Reconnecting --> Connected : success\n Reconnecting --> Closed : max_retries\n Disconnecting --> Closed : done\n Closed --> [*]","category":"State","options":{}},{"title":"Sequence: Basic Messages","description":"Simple request/response between two participants.","source":"sequenceDiagram\n Alice->>Bob: Hello Bob!\n Bob-->>Alice: Hi Alice!","category":"Sequence","options":{}},{"title":"Sequence: Participant Aliases","description":"Using `participant ... as ...` for compact diagram IDs with readable labels.","source":"sequenceDiagram\n participant A as Alice\n participant B as Bob\n participant C as Charlie\n A->>B: Hello\n B->>C: Forward\n C-->>A: Reply","category":"Sequence","options":{}},{"title":"Sequence: Actor Stick Figures","description":"Using `actor` instead of `participant` renders stick figures instead of boxes.","source":"sequenceDiagram\n actor U as User\n participant S as System\n participant DB as Database\n U->>S: Click button\n S->>DB: Query\n DB-->>S: Results\n S-->>U: Display","category":"Sequence","options":{}},{"title":"Sequence: Arrow Types","description":"All arrow types: solid `->>` and dashed `-->>` with filled arrowheads, open arrows `-)` .","source":"sequenceDiagram\n A->>B: Solid arrow (sync)\n B-->>A: Dashed arrow (return)\n A-)B: Open arrow (async)\n B--)A: Open dashed arrow","category":"Sequence","options":{}},{"title":"Sequence: Activation Boxes","description":"Using `+` and `-` to show when participants are active.","source":"sequenceDiagram\n participant C as Client\n participant S as Server\n C->>+S: Request\n S->>+S: Process\n S->>-S: Done\n S-->>-C: Response","category":"Sequence","options":{}},{"title":"Sequence: Self-Messages","description":"A participant sending a message to itself (displayed as a loop arrow).","source":"sequenceDiagram\n participant S as Server\n S->>S: Internal process\n S->>S: Validate\n S-->>S: Log","category":"Sequence","options":{}},{"title":"Sequence: Loop Block","description":"A `loop` construct wrapping repeated message exchanges.","source":"sequenceDiagram\n participant C as Client\n participant S as Server\n C->>S: Connect\n loop Every 30s\n C->>S: Heartbeat\n S-->>C: Ack\n end\n C->>S: Disconnect","category":"Sequence","options":{}},{"title":"Sequence: Alt/Else Block","description":"Conditional branching with `alt` (if) and `else` blocks.","source":"sequenceDiagram\n participant C as Client\n participant S as Server\n C->>S: Login\n alt Valid credentials\n S-->>C: 200 OK\n else Invalid\n S-->>C: 401 Unauthorized\n else Account locked\n S-->>C: 403 Forbidden\n end","category":"Sequence","options":{}},{"title":"Sequence: Opt Block","description":"Optional block — executes only if condition is met.","source":"sequenceDiagram\n participant A as App\n participant C as Cache\n participant DB as Database\n A->>C: Get data\n C-->>A: Cache miss\n opt Cache miss\n A->>DB: Query\n DB-->>A: Results\n A->>C: Store in cache\n end","category":"Sequence","options":{}},{"title":"Sequence: Par Block","description":"Parallel execution with `par`/`and` constructs.","source":"sequenceDiagram\n participant C as Client\n participant A as AuthService\n participant U as UserService\n participant O as OrderService\n C->>A: Authenticate\n par Fetch user data\n A->>U: Get profile\n and Fetch orders\n A->>O: Get orders\n end\n A-->>C: Combined response","category":"Sequence","options":{}},{"title":"Sequence: Critical Block","description":"Critical section that must complete atomically.","source":"sequenceDiagram\n participant A as App\n participant DB as Database\n A->>DB: BEGIN\n critical Transaction\n A->>DB: UPDATE accounts\n A->>DB: INSERT log\n end\n A->>DB: COMMIT","category":"Sequence","options":{}},{"title":"Sequence: Notes (Right/Left/Over)","description":"Notes positioned to the right, left, or over participants.","source":"sequenceDiagram\n participant A as Alice\n participant B as Bob\n Note left of A: Alice prepares\n A->>B: Hello\n Note right of B: Bob thinks\n B-->>A: Reply\n Note over A,B: Conversation complete","category":"Sequence","options":{}},{"title":"Sequence: OAuth 2.0 Flow","description":"Full OAuth 2.0 authorization code flow with token exchange.","source":"sequenceDiagram\n actor U as User\n participant App as Client App\n participant Auth as Auth Server\n participant API as Resource API\n U->>App: Click Login\n App->>Auth: Authorization request\n Auth->>U: Login page\n U->>Auth: Credentials\n Auth-->>App: Authorization code\n App->>Auth: Exchange code for token\n Auth-->>App: Access token\n App->>API: Request + token\n API-->>App: Protected resource\n App-->>U: Display data","category":"Sequence","options":{}},{"title":"Sequence: Database Transaction","description":"Multi-step database transaction with rollback handling.","source":"sequenceDiagram\n participant C as Client\n participant S as Server\n participant DB as Database\n C->>S: POST /transfer\n S->>DB: BEGIN\n S->>DB: Debit account A\n alt Success\n S->>DB: Credit account B\n S->>DB: INSERT audit_log\n S->>DB: COMMIT\n S-->>C: 200 OK\n else Insufficient funds\n S->>DB: ROLLBACK\n S-->>C: 400 Bad Request\n end","category":"Sequence","options":{}},{"title":"Sequence: Microservice Orchestration","description":"Complex multi-service flow with parallel calls and error handling.","source":"sequenceDiagram\n participant G as Gateway\n participant A as Auth\n participant U as Users\n participant O as Orders\n participant N as Notify\n G->>A: Validate token\n A-->>G: Valid\n par Fetch data\n G->>U: Get user\n U-->>G: User data\n and\n G->>O: Get orders\n O-->>G: Order list\n end\n G->>N: Send notification\n N-->>G: Queued\n Note over G: Aggregate response","category":"Sequence","options":{}},{"title":"Class: Basic Class","description":"A single class with attributes and methods, rendered as a 3-compartment box.","source":"classDiagram\n class Animal {\n +String name\n +int age\n +eat() void\n +sleep() void\n }","category":"Class","options":{}},{"title":"Class: Visibility Markers","description":"All four visibility levels: `+` (public), `-` (private), `#` (protected), `~` (package).","source":"classDiagram\n class User {\n +String name\n -String password\n #int internalId\n ~String packageField\n +login() bool\n -hashPassword() String\n #validate() void\n ~notify() void\n }","category":"Class","options":{}},{"title":"Class: Interface Annotation","description":"Using `<>` annotation above the class name.","source":"classDiagram\n class Serializable {\n <>\n +serialize() String\n +deserialize(data) void\n }","category":"Class","options":{}},{"title":"Class: Abstract Annotation","description":"Using `<>` annotation for abstract classes.","source":"classDiagram\n class Shape {\n <>\n +String color\n +area() double\n +draw() void\n }","category":"Class","options":{}},{"title":"Class: Enum Annotation","description":"Using `<>` annotation for enum types.","source":"classDiagram\n class Status {\n <>\n ACTIVE\n INACTIVE\n PENDING\n DELETED\n }","category":"Class","options":{}},{"title":"Class: Inheritance (<|--)","description":"Inheritance relationship rendered with a hollow triangle marker.","source":"classDiagram\n class Animal {\n +String name\n +eat() void\n }\n class Dog {\n +String breed\n +bark() void\n }\n class Cat {\n +bool isIndoor\n +meow() void\n }\n Animal <|-- Dog\n Animal <|-- Cat","category":"Class","options":{}},{"title":"Class: Composition (*--)","description":"Composition — \"owns\" relationship with filled diamond marker.","source":"classDiagram\n class Car {\n +String model\n +start() void\n }\n class Engine {\n +int horsepower\n +rev() void\n }\n Car *-- Engine","category":"Class","options":{}},{"title":"Class: Aggregation (o--)","description":"Aggregation — \"has\" relationship with hollow diamond marker.","source":"classDiagram\n class University {\n +String name\n }\n class Department {\n +String faculty\n }\n University o-- Department","category":"Class","options":{}},{"title":"Class: Association (-->)","description":"Basic association — simple directed arrow.","source":"classDiagram\n class Customer {\n +String name\n }\n class Order {\n +int orderId\n }\n Customer --> Order","category":"Class","options":{}},{"title":"Class: Dependency (..>)","description":"Dependency — dashed line with open arrow.","source":"classDiagram\n class Service {\n +process() void\n }\n class Repository {\n +find() Object\n }\n Service ..> Repository","category":"Class","options":{}},{"title":"Class: Realization (..|>)","description":"Realization — dashed line with hollow triangle (implements interface).","source":"classDiagram\n class Flyable {\n <>\n +fly() void\n }\n class Bird {\n +fly() void\n +sing() void\n }\n Bird ..|> Flyable","category":"Class","options":{}},{"title":"Class: All 6 Relationship Types","description":"Every relationship type in a single diagram for comparison.","source":"classDiagram\n A <|-- B : inheritance\n C *-- D : composition\n E o-- F : aggregation\n G --> H : association\n I ..> J : dependency\n K ..|> L : realization","category":"Class","options":{}},{"title":"Class: Relationship Labels","description":"Labeled relationships between classes with descriptive text.","source":"classDiagram\n class Teacher {\n +String name\n }\n class Student {\n +String name\n }\n class Course {\n +String title\n }\n Teacher --> Course : teaches\n Student --> Course : enrolled in","category":"Class","options":{}},{"title":"Class: Design Pattern — Observer","description":"The Observer (publish-subscribe) design pattern with interface + concrete implementations.","source":"classDiagram\n class Subject {\n <>\n +attach(Observer) void\n +detach(Observer) void\n +notify() void\n }\n class Observer {\n <>\n +update() void\n }\n class EventEmitter {\n -List~Observer~ observers\n +attach(Observer) void\n +detach(Observer) void\n +notify() void\n }\n class Logger {\n +update() void\n }\n class Alerter {\n +update() void\n }\n Subject <|.. EventEmitter\n Observer <|.. Logger\n Observer <|.. Alerter\n EventEmitter --> Observer","category":"Class","options":{}},{"title":"Class: MVC Architecture","description":"Model-View-Controller pattern showing relationships between layers.","source":"classDiagram\n class Model {\n -data Map\n +getData() Map\n +setData(key, val) void\n +notify() void\n }\n class View {\n -model Model\n +render() void\n +update() void\n }\n class Controller {\n -model Model\n -view View\n +handleInput(event) void\n +updateModel(data) void\n }\n Controller --> Model : updates\n Controller --> View : refreshes\n View --> Model : reads\n Model ..> View : notifies","category":"Class","options":{}},{"title":"Class: Full Hierarchy","description":"A complete class hierarchy with abstract base, interfaces, and concrete classes.","source":"classDiagram\n class Animal {\n <>\n +String name\n +int age\n +eat() void\n +sleep() void\n }\n class Mammal {\n +bool warmBlooded\n +nurse() void\n }\n class Bird {\n +bool canFly\n +layEggs() void\n }\n class Dog {\n +String breed\n +bark() void\n }\n class Cat {\n +bool isIndoor\n +purr() void\n }\n class Parrot {\n +String vocabulary\n +speak() void\n }\n Animal <|-- Mammal\n Animal <|-- Bird\n Mammal <|-- Dog\n Mammal <|-- Cat\n Bird <|-- Parrot","category":"Class","options":{}},{"title":"ER: Basic Relationship","description":"A simple one-to-many relationship between two entities.","source":"erDiagram\n CUSTOMER ||--o{ ORDER : places","category":"ER","options":{}},{"title":"ER: Entity with Attributes","description":"An entity with typed attributes and `PK`/`FK`/`UK` key badges.","source":"erDiagram\n CUSTOMER {\n int id PK\n string name\n string email UK\n date created_at\n }","category":"ER","options":{}},{"title":"ER: Attribute Keys (PK, FK, UK)","description":"All three key constraint types rendered as badges.","source":"erDiagram\n ORDER {\n int id PK\n int customer_id FK\n string invoice_number UK\n decimal total\n date order_date\n string status\n }","category":"ER","options":{}},{"title":"ER: Exactly One to Exactly One (||--||)","description":"One-to-one mandatory relationship.","source":"erDiagram\n PERSON ||--|| PASSPORT : has","category":"ER","options":{}},{"title":"ER: Exactly One to Zero-or-Many (||--o{)","description":"Classic one-to-many optional relationship (crow's foot).","source":"erDiagram\n CUSTOMER ||--o{ ORDER : places","category":"ER","options":{}},{"title":"ER: Zero-or-One to One-or-Many (|o--|{)","description":"Optional on one side, at-least-one on the other.","source":"erDiagram\n SUPERVISOR |o--|{ EMPLOYEE : manages","category":"ER","options":{}},{"title":"ER: One-or-More to Zero-or-Many (}|--o{)","description":"At-least-one to zero-or-many relationship.","source":"erDiagram\n TEACHER }|--o{ COURSE : teaches","category":"ER","options":{}},{"title":"ER: All Cardinality Types","description":"Every cardinality combination in one diagram.","source":"erDiagram\n A ||--|| B : one-to-one\n C ||--o{ D : one-to-many\n E |o--|{ F : opt-to-many\n G }|--o{ H : many-to-many","category":"ER","options":{}},{"title":"ER: Identifying (Solid) Relationship","description":"Solid line indicating an identifying relationship (child depends on parent for identity).","source":"erDiagram\n ORDER ||--|{ LINE_ITEM : contains","category":"ER","options":{}},{"title":"ER: Non-Identifying (Dashed) Relationship","description":"Dashed line indicating a non-identifying relationship.","source":"erDiagram\n USER ||..o{ LOG_ENTRY : generates\n USER ||..o{ SESSION : opens","category":"ER","options":{}},{"title":"ER: Mixed Identifying & Non-Identifying","description":"Both solid and dashed lines in the same diagram.","source":"erDiagram\n ORDER ||--|{ LINE_ITEM : contains\n ORDER ||..o{ SHIPMENT : ships-via\n PRODUCT ||--o{ LINE_ITEM : includes\n PRODUCT ||..o{ REVIEW : receives","category":"ER","options":{}},{"title":"ER: E-Commerce Schema","description":"Full e-commerce database schema with customers, orders, products, and line items.","source":"erDiagram\n CUSTOMER {\n int id PK\n string name\n string email UK\n }\n ORDER {\n int id PK\n date created\n int customer_id FK\n }\n PRODUCT {\n int id PK\n string name\n float price\n }\n LINE_ITEM {\n int id PK\n int order_id FK\n int product_id FK\n int quantity\n }\n CUSTOMER ||--o{ ORDER : places\n ORDER ||--|{ LINE_ITEM : contains\n PRODUCT ||--o{ LINE_ITEM : includes","category":"ER","options":{}},{"title":"ER: Blog Platform Schema","description":"Blog system with users, posts, comments, and tags.","source":"erDiagram\n USER {\n int id PK\n string username UK\n string email UK\n date joined\n }\n POST {\n int id PK\n string title\n text content\n int author_id FK\n date published\n }\n COMMENT {\n int id PK\n text body\n int post_id FK\n int user_id FK\n date created\n }\n TAG {\n int id PK\n string name UK\n }\n USER ||--o{ POST : writes\n USER ||--o{ COMMENT : authors\n POST ||--o{ COMMENT : has\n POST }|--o{ TAG : tagged-with","category":"ER","options":{}},{"title":"ER: School Management Schema","description":"School system with students, teachers, courses, and enrollments.","source":"erDiagram\n STUDENT {\n int id PK\n string name\n date dob\n string grade\n }\n TEACHER {\n int id PK\n string name\n string department\n }\n COURSE {\n int id PK\n string title\n int teacher_id FK\n int credits\n }\n ENROLLMENT {\n int id PK\n int student_id FK\n int course_id FK\n string semester\n float grade\n }\n TEACHER ||--o{ COURSE : teaches\n STUDENT ||--o{ ENROLLMENT : enrolled\n COURSE ||--o{ ENROLLMENT : has","category":"ER","options":{}}]; var THEMES = window.__mermaid.THEMES; var renderMermaid = window.__mermaid.renderMermaid; var renderMermaidAscii = window.__mermaid.renderMermaidAscii; var totalTimingEl = document.getElementById('total-timing'); // -- Theme state -- // Stores each SVG element's original inline style attribute (from initial render) // so we can restore per-sample colors when switching back to "Default". var originalSvgStyles = []; function hexToRgb(hex) { if (!hex || typeof hex !== 'string') return null; var value = hex.trim(); if (value[0] === '#') value = value.slice(1); if (value.length === 3) { value = value[0] + value[0] + value[1] + value[1] + value[2] + value[2]; } if (value.length !== 6) return null; var intValue = parseInt(value, 16); if (Number.isNaN(intValue)) return null; return { r: (intValue >> 16) & 255, g: (intValue >> 8) & 255, b: intValue & 255, }; } function setShadowVars(theme) { var body = document.body; var fg = theme ? theme.fg : '#27272A'; var bg = theme ? theme.bg : '#FFFFFF'; var accent = theme ? (theme.accent || '#3b82f6') : '#3b82f6'; var fgRgb = hexToRgb(fg) || { r: 39, g: 39, b: 42 }; var bgRgb = hexToRgb(bg) || { r: 255, g: 255, b: 255 }; var accentRgb = hexToRgb(accent) || { r: 59, g: 130, b: 246 }; var brightness = (bgRgb.r * 299 + bgRgb.g * 587 + bgRgb.b * 114) / 1000; var darkMode = brightness < 140; body.style.setProperty('--foreground-rgb', fgRgb.r + ', ' + fgRgb.g + ', ' + fgRgb.b); body.style.setProperty('--accent-rgb', accentRgb.r + ', ' + accentRgb.g + ', ' + accentRgb.b); body.style.setProperty('--shadow-border-opacity', darkMode ? '0.15' : '0.08'); body.style.setProperty('--shadow-blur-opacity', darkMode ? '0.12' : '0.06'); } // Update so Safari 26+ title bar matches the page. // Computes color-mix(in srgb, fg 4%, bg) in JS since browsers may not // reliably re-evaluate CSS color-mix() for the meta tag. function updateThemeColor(fg, bg) { var fgRgb = hexToRgb(fg) || { r: 39, g: 39, b: 42 }; var bgRgb = hexToRgb(bg) || { r: 255, g: 255, b: 255 }; // Mix: 4% foreground, 96% background (matches body CSS) var r = Math.round(bgRgb.r * 0.96 + fgRgb.r * 0.04); var g = Math.round(bgRgb.g * 0.96 + fgRgb.g * 0.04); var b = Math.round(bgRgb.b * 0.96 + fgRgb.b * 0.04); var hex = '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1); document.getElementById('theme-color-meta').setAttribute('content', hex); // Update --theme-bar-bg on body so gradients update instantly document.body.style.setProperty('--theme-bar-bg', hex); // Force Safari 26+ to re-read title bar color by updating the invisible fixed div // and triggering a reflow (display toggle + offsetHeight read) var safariDiv = document.getElementById('safari-theme-color'); safariDiv.style.background = hex; safariDiv.style.display = 'none'; void safariDiv.offsetHeight; safariDiv.style.display = ''; } // ---------------------------------------------------------------- // Apply a named theme (or '' for Default) to the entire page. // // This is instant — no re-rendering needed. SVGs use CSS custom // properties internally, so updating --bg/--fg on the tag // re-paints all nodes, edges, text, and backgrounds via color-mix(). // ---------------------------------------------------------------- function applyTheme(themeKey) { var theme = themeKey ? THEMES[themeKey] : null; var body = document.body; // 1. Update body CSS variables — the entire page derives from these if (theme) { body.style.setProperty('--t-bg', theme.bg); body.style.setProperty('--t-fg', theme.fg); body.style.setProperty('--t-accent', theme.accent || '#3b82f6'); } else { body.style.setProperty('--t-bg', '#FFFFFF'); body.style.setProperty('--t-fg', '#27272A'); body.style.setProperty('--t-accent', '#3b82f6'); } setShadowVars(theme); updateThemeColor(theme ? theme.fg : '#27272A', theme ? theme.bg : '#FFFFFF'); // 2. Update all rendered SVG elements' CSS variables var svgs = document.querySelectorAll('.svg-container svg'); for (var j = 0; j < svgs.length; j++) { var svgEl = svgs[j]; if (theme) { // Override with the global theme colors svgEl.style.setProperty('--bg', theme.bg); svgEl.style.setProperty('--fg', theme.fg); // Set enrichment variables if provided, else remove so SVG // internal color-mix() fallbacks activate var enrichment = ['line', 'accent', 'muted', 'surface', 'border']; for (var k = 0; k < enrichment.length; k++) { var prop = enrichment[k]; if (theme[prop]) svgEl.style.setProperty('--' + prop, theme[prop]); else svgEl.style.removeProperty('--' + prop); } } else { // Restore original inline style from initial render if (originalSvgStyles[j] !== undefined) { svgEl.setAttribute('style', originalSvgStyles[j]); } } } // 3. Update SVG panel backgrounds to match (skip hero panels - keep transparent) for (var j = 0; j < samples.length; j++) { var panel = document.getElementById('svg-panel-' + j); if (!panel) continue; // Skip hero panels - they stay transparent if (panel.classList.contains('hero-diagram-panel')) continue; if (theme) { panel.style.background = theme.bg; } else { // Default mode: use the per-sample bg (or clear for page default) var sampleBg = panel.getAttribute('data-sample-bg'); panel.style.background = sampleBg || ''; } } // 4. Update active pill var pills = document.querySelectorAll('.theme-pill'); for (var j = 0; j < pills.length; j++) { var isActive = pills[j].getAttribute('data-theme') === themeKey; pills[j].classList.toggle('active', isActive); pills[j].classList.toggle('shadow-tinted', isActive); } // 5. Persist selection if (themeKey) { localStorage.setItem('mermaid-theme', themeKey); } else { localStorage.removeItem('mermaid-theme'); } } // -- Set up theme pill click handlers -- document.getElementById('theme-pills').addEventListener('click', function(e) { var pill = e.target.closest('.theme-pill'); if (!pill || pill.id === 'theme-more-btn') return; applyTheme(pill.getAttribute('data-theme') || ''); // Close "More" dropdown if a theme was picked from it var dd = document.getElementById('theme-more-dropdown'); if (dd && dd.classList.contains('open')) dd.classList.remove('open'); }); // -- "More" themes dropdown (direct listener, same pattern as Contents) -- var moreBtn = document.getElementById('theme-more-btn'); var moreDropdown = document.getElementById('theme-more-dropdown'); if (moreBtn && moreDropdown) { moreBtn.addEventListener('click', function(e) { e.stopPropagation(); moreDropdown.classList.toggle('open'); }); // Close on outside click document.addEventListener('click', function(e) { if (!moreDropdown.classList.contains('open')) return; if (!e.target.closest('.theme-more-wrapper')) { moreDropdown.classList.remove('open'); } }); // Close on Escape document.addEventListener('keydown', function(e) { if (e.key === 'Escape' && moreDropdown.classList.contains('open')) { moreDropdown.classList.remove('open'); } }); } // -- Random theme button -- var randomThemeBtn = document.getElementById('random-theme-btn'); var themeKeys = Object.keys(THEMES); var currentThemeKey = localStorage.getItem('mermaid-theme') || ''; if (randomThemeBtn) { randomThemeBtn.addEventListener('click', function() { // Filter out the current theme so we never pick the same one var availableKeys = themeKeys.filter(function(k) { return k !== currentThemeKey; }); // Also include default ('') if not currently selected if (currentThemeKey !== '') availableKeys.push(''); // Pick a random theme var randomIndex = Math.floor(Math.random() * availableKeys.length); var newThemeKey = availableKeys[randomIndex]; currentThemeKey = newThemeKey; applyTheme(newThemeKey); }); } // -- Brand dropdown -- var brandBtn = document.getElementById('brand-badge-btn'); var brandDropdown = document.getElementById('brand-dropdown'); if (brandBtn && brandDropdown) { brandBtn.addEventListener('click', function(e) { e.stopPropagation(); var isOpen = brandDropdown.classList.toggle('open'); brandBtn.classList.toggle('active', isOpen); brandBtn.classList.toggle('shadow-tinted', isOpen); }); // Close on outside click document.addEventListener('click', function(e) { if (!brandDropdown.classList.contains('open')) return; if (!e.target.closest('.brand-badge-wrapper')) { brandDropdown.classList.remove('open'); brandBtn.classList.remove('active'); brandBtn.classList.remove('shadow-tinted'); } }); // Close on Escape document.addEventListener('keydown', function(e) { if (e.key === 'Escape' && brandDropdown.classList.contains('open')) { brandDropdown.classList.remove('open'); brandBtn.classList.remove('active'); brandBtn.classList.remove('shadow-tinted'); } }); } // -- Mega menu (Contents dropdown) -- var contentsBtn = document.getElementById('contents-btn'); var megaMenu = document.getElementById('mega-menu'); contentsBtn.addEventListener('click', function(e) { e.stopPropagation(); var isOpen = megaMenu.classList.toggle('open'); contentsBtn.classList.toggle('active', isOpen); contentsBtn.classList.toggle('shadow-tinted', isOpen); }); // Close on clicking a ToC link (smooth scroll to target) megaMenu.addEventListener('click', function(e) { var link = e.target.closest('a'); if (!link) return; e.preventDefault(); megaMenu.classList.remove('open'); contentsBtn.classList.remove('active'); contentsBtn.classList.remove('shadow-tinted'); var target = document.querySelector(link.getAttribute('href')); if (target) target.scrollIntoView({ behavior: 'smooth', block: 'start' }); }); // Close on outside click document.addEventListener('click', function(e) { if (!megaMenu.classList.contains('open')) return; if (!e.target.closest('.mega-menu') && !e.target.closest('.contents-btn')) { megaMenu.classList.remove('open'); contentsBtn.classList.remove('active'); contentsBtn.classList.remove('shadow-tinted'); } }); // Close on Escape document.addEventListener('keydown', function(e) { if (e.key === 'Escape' && megaMenu.classList.contains('open')) { megaMenu.classList.remove('open'); contentsBtn.classList.remove('active'); contentsBtn.classList.remove('shadow-tinted'); } }); // -- Restore saved theme immediately (before rendering begins) -- var savedTheme = localStorage.getItem('mermaid-theme'); if (savedTheme && THEMES[savedTheme]) { // Apply page-level CSS variables right away to avoid flash document.body.style.setProperty('--t-bg', THEMES[savedTheme].bg); document.body.style.setProperty('--t-fg', THEMES[savedTheme].fg); document.body.style.setProperty('--t-accent', THEMES[savedTheme].accent || '#3b82f6'); setShadowVars(THEMES[savedTheme]); updateThemeColor(THEMES[savedTheme].fg, THEMES[savedTheme].bg); // Mark the correct pill as active var pills = document.querySelectorAll('.theme-pill'); for (var j = 0; j < pills.length; j++) { var isActive = pills[j].getAttribute('data-theme') === savedTheme; pills[j].classList.toggle('active', isActive); pills[j].classList.toggle('shadow-tinted', isActive); } } else { setShadowVars(null); } // ============================================================================ // Progressive rendering — render each diagram sequentially // ============================================================================ var totalStart = performance.now(); for (var i = 0; i < samples.length; i++) { var sample = samples[i]; var svgContainer = document.getElementById('svg-' + i); var asciiContainer = document.getElementById('ascii-' + i); var svgPanel = document.getElementById('svg-panel-' + i); // Render SVG — wrapped in a timeout guard so a stalled layout // doesn't block all remaining diagrams from rendering. try { var svg = await renderMermaid(sample.source, sample.options); svgContainer.innerHTML = svg; // Store the SVG's original inline style for Default mode restoration var svgEl = svgContainer.querySelector('svg'); if (svgEl) { originalSvgStyles.push(svgEl.getAttribute('style') || ''); // If a global theme is active, immediately override the SVG's variables if (savedTheme && THEMES[savedTheme]) { var th = THEMES[savedTheme]; svgEl.style.setProperty('--bg', th.bg); svgEl.style.setProperty('--fg', th.fg); var enrichment = ['line', 'accent', 'muted', 'surface', 'border']; for (var k = 0; k < enrichment.length; k++) { if (th[enrichment[k]]) svgEl.style.setProperty('--' + enrichment[k], th[enrichment[k]]); else svgEl.style.removeProperty('--' + enrichment[k]); } } } else { originalSvgStyles.push(''); } // Set panel background to match the SVG (skip for hero panels - keep transparent) var isHeroPanel = svgPanel.classList.contains('hero-diagram-panel'); if (!isHeroPanel) { if (savedTheme && THEMES[savedTheme]) { svgPanel.style.background = THEMES[savedTheme].bg; } else { var sampleBg = svgPanel.getAttribute('data-sample-bg'); if (sampleBg) svgPanel.style.background = sampleBg; } } } catch (err) { svgContainer.innerHTML = '
SVG Error: ' + escapeHtml(String(err)) + '
'; originalSvgStyles.push(''); } // Hero samples don't have ASCII panels if (asciiContainer) { try { asciiContainer.textContent = renderMermaidAscii(sample.source); } catch (e) { asciiContainer.textContent = '(ASCII not supported for this diagram type)'; } } } // Done — show total time var totalMs = (performance.now() - totalStart).toFixed(0); totalTimingEl.textContent = (samples.length * 2) + ' samples (SVG+ASCII) rendered in ' + totalMs + ' ms'; function escapeHtml(text) { return text.replace(/&/g, '&').replace(//g, '>'); }