finsteps

MPD Grammar Documentation

This document provides a comprehensive guide to the MPD (Mermaid Presentation DSL) grammar, including the formal EBNF specification, quick reference, and examples.

Overview

MPD (Mermaid Presentation DSL) is a declarative language for defining interactive presentations over Mermaid diagrams. The grammar is formally specified in EBNF notation.

Program Structure

Every MPD program starts with a version header:

mpd 1.0

deck {
  // Presentation content
}

Top-Level Constructs

Deck

A deck is the root container for presentation content:

mpd 1.0

deck {
  scene default {
    step overview {
      camera reset();
      overlay bubble(target: dataId("A"), text: "Welcome!");
    }
  }
}

Scene

A scene groups related steps and can optionally reference a specific diagram:

scene intro {
  step overview {
    camera reset();
  }
  
  step detail {
    camera fit(target: dataId("B"));
  }
}

scene outro diagram "main-diagram" {
  step summary {
    camera fitAll();
  }
}

Step

A step defines a presentation state with actions:

step overview {
  camera reset();
  style highlight(target: dataId("A"));
  overlay bubble(target: dataId("A"), text: "Start here");
}

Binding

A binding defines event-to-action mappings:

binding {
  on click target node("A") {
    do nav.goto(id: "detail");
  }
  
  on key "ArrowRight" {
    do nav.next();
  }
}

Expressions

Literals

let count = 42;              // Integer
let rate = 0.95;             // Number
let message = "Hello";       // String
let enabled = true;          // Boolean
let empty = null;            // Null
let duration = 500ms;        // Duration
let percent = 50%;           // Percent
let color = #3b82f6;        // Color hex

Objects and Arrays

let config = {
  theme: "dark",
  fontSize: 14,
  enabled: true
};

let items = [1, 2, 3, "four"];

Target Expressions

Target expressions select diagram elements:

node("A")                    // Node by ID
edge("A", "B")               // Edge between nodes
subgraph("cluster1")         // Subgraph by ID
css(".highlight")            // CSS selector
id("element-id")             // Element by ID
text("Label")                // Element by text content
dataId("nodeA")              // Element by data-id attribute

// Target combinations
union(node("A"), node("B"))  // Union of targets
intersect(target1, target2)  // Intersection
except(all, node("A"))       // All except A
group(node("A"), node("B"))  // Grouped selection

Actions

Camera Actions

camera fit(target: dataId("A"), padding: 60, duration: 500, easing: "cubicOut");
camera reset();
camera zoom(factor: 1.2, center: { x: 100, y: 100 });
camera pan(deltaX: 50, deltaY: 0);
camera fitAll(padding: 40);

Style Actions

style highlight(target: dataId("A"));
style clear();
style classAdd(target: node("B"), className: "active");
style classRemove(target: node("B"), className: "inactive");

Overlay Actions

overlay bubble(target: dataId("A"), text: "Important note!");
overlay hide(id: "bubble-1");
nav.next();
nav.prev();
nav.goto(id: "overview");
nav.goto(index: 2);
nav.reset();

Focus Statements

Focus statements combine camera positioning with optional styling:

focus node("A") pad 60 align center lock xy id "main-focus";

Focus options:

Runtime Configuration

Camera Configuration

runtime {
  camera {
    engine: "basic";
    options: {
      minZoom: 0.5,
      maxZoom: 3.0
    };
    bounds: viewport;
  }
}

Overlay Configuration

runtime {
  overlay {
    engine: "basic";
    options: {
      placement: "top",
      offset: 10
    };
  }
}
runtime {
  navigation {
    wheelZoom: true;
    dragPan: true;
    tapToAdvance: true;
    progressUI: true;
    startAt: "overview";
    keys: {
      next: "ArrowRight",
      prev: "ArrowLeft"
    };
  }
}

Controls Configuration

runtime {
  controls {
    mode: "floating";
    position: "bottom-right";
    showPlayPause: true;
    showPrevNext: true;
    showZoomControls: true;
    showStepIndicator: true;
    autoHide: false;
    offset: { x: 20, y: 20 };
  }
}

Controls configuration options:

Controls can also be configured programmatically via JavaScript:

import { presentMermaid, createFloatingControls } from 'finsteps';

const controller = await presentMermaid({
  mountEl,
  mermaidText,
  mpdText,
  options: {
    controls: createFloatingControls({
      controller, // Will be set automatically
      camera,     // Optional, for zoom controls
      position: 'bottom-right',
      showPlayPause: true,
      showPrevNext: true,
      showZoomControls: true
    })
  }
});

Diagram Declaration

Diagrams can be declared inline or referenced by ID:

diagram "main" {
  mermaid <<<MERMAID
    flowchart LR
      A[Start] --> B[End]
  MERMAID;
  
  config {
    theme: "dark",
    flowchart: {
      curve: "basis"
    }
  };
}

Selectors

Configure how targets resolve to diagram elements:

selectors {
  strategy: mermaid-node-id;
  fallback: [css, text];
  node: {
    prefix: "node-",
    dataId: true
  };
  edge: {
    prefix: "edge-",
    byLabel: true
  };
}

Styles

Define custom CSS classes and spotlight effects:

styles {
  classes: {
    highlight: "finsteps-highlight",
    dim: "finsteps-dim"
  };
  spotlight: {
    activeClass: "finsteps-active",
    inactiveClass: "finsteps-inactive"
  };
  theme: dark;
}

Complete Example

mpd 1.0

deck {
  runtime {
    camera {
      engine: "basic";
      bounds: viewport;
    }
    navigation {
      wheelZoom: true;
      dragPan: true;
      startAt: "overview";
    }
  }
  
  scene default {
    step overview {
      camera reset();
      overlay bubble(target: dataId("A"), text: "Full diagram view");
    }
    
    step detail {
      camera fit(target: dataId("B"), padding: 60, duration: 500);
      style highlight(target: dataId("B"));
      overlay bubble(target: dataId("B"), text: "Detailed view");
    }
  }
  
  binding {
    on key "ArrowRight" {
      do nav.next();
    }
    on key "ArrowLeft" {
      do nav.prev();
    }
    on click target node("B") {
      do nav.goto(id: "detail");
    }
  }
}

Formal Grammar

The complete EBNF grammar is available in ebnf/mpd.ebnf. This formal specification defines:

Validation

MPD can be validated using: