Skip to content

feat: add match visualization DSL to docs#38

Merged
elasticdotventures merged 2 commits into
mainfrom
feat/match-visualization-dsl
Apr 21, 2026
Merged

feat: add match visualization DSL to docs#38
elasticdotventures merged 2 commits into
mainfrom
feat/match-visualization-dsl

Conversation

@elasticdotventures
Copy link
Copy Markdown
Member

What changed

  • add first-class match expr => Arm -> target support to the mdBook Rhai->Mermaid preprocessor
  • mirror the same match-arm DSL in the live docs editor and isometric renderer
  • expand visualization docs with a dedicated match visualization plan and richer sample gallery
  • tighten docs validation and CI so the real just docgen-check gate runs in GitHub Actions

Validation

  • cargo test -p mdbook-rhai-mermaid
  • node --test book/theme/rhai-live-core.test.js
  • just docgen-check

Copilot AI review requested due to automatic review settings April 20, 2026 14:25
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds match expr => Arm -> target as a first-class diagram DSL construct across the mdBook Rhai→Mermaid preprocessor and the live docs editor, expanding docs/CI to validate the new visualization behaviors.

Changes:

  • Extend the Rust parser/emitter to support match nodes with labeled outgoing arms (plus tests).
  • Upgrade the live docs editor to support match-arm parsing and add an isometric SVG renderer with a view-mode toggle (plus JS unit tests).
  • Expand documentation with a new “Match Visualization Plan” chapter and tighten docgen-check/CI to run the real docs validation gate.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
crates/mdbook-rhai-mermaid/src/parser.rs Adds NodeKind::Match, parses match-arm statements, and groups them into a single match node.
crates/mdbook-rhai-mermaid/src/emitter.rs Renders match nodes as diamonds and escapes edge labels; adds match-focused tests.
crates/mdbook-rhai-mermaid/src/main.rs Adds an injection test ensuring match blocks produce Mermaid output.
book/theme/rhai-live.js Adds view-mode toggle (Mermaid vs isometric), persistence, improved error rendering, and updated UI copy.
book/theme/rhai-live.css Styles the new toolbar/switcher and adds isometric-scene styling.
book/theme/rhai-live-core.js Adds match parsing, Mermaid label escaping, deterministic isometric layout + SVG renderer, and richer diagnostics helpers.
book/theme/rhai-live-core.test.js Adds tests for match parsing/Mermaid output, deterministic layout, SVG rendering/animation, and failure guidance.
book/src/visualize.md Documents the match DSL, new dual-view editor, and adds a sample gallery including a match example.
book/src/theory.md Adds a cross-link to the match visualization plan from match-heavy examples.
book/src/match-visualization-plan.md New chapter describing intended match rendering semantics and acceptance criteria.
book/src/SUMMARY.md Adds the new chapter to the mdBook navigation (and adjusts Ledger Ops placement).
README.md Notes the dual-view live editor modes and their intent.
Justfile Strengthens docgen-check (new link/content assertions + JS syntax checks).
.github/workflows/ci.yml Updates CI to run just docgen-check (and installs required tooling).
AGENTS.md Updates contributor guidance to include match DSL and the new live editor rendering contract.
Comments suppressed due to low confidence (1)

crates/mdbook-rhai-mermaid/src/parser.rs:95

  • The docstring for parse says it “Returns None only if the source contains no parseable statements”, but parse returns Graph (never Option). This is misleading for callers/readers; please update the comment to reflect the current return type/behavior (e.g., “returns an empty Graph when no statements are found”).
/// Parse the rhai pseudo-DSL source into a `Graph`.
///
/// Returns `None` only if the source contains no parseable statements at all
/// (empty/comment-only). Malformed lines are silently skipped so a partial
/// parse always succeeds.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread book/theme/rhai-live.js Outdated
Comment on lines +95 to +101
const stored = window.localStorage ? window.localStorage.getItem(STORAGE_KEY) : null;
return stored === "mermaid-2d" ? "mermaid-2d" : "isometric-3d";
}

function persistViewMode(mode) {
if (window.localStorage) {
window.localStorage.setItem(STORAGE_KEY, mode);
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

selectedViewMode() / persistViewMode() assume window.localStorage is always readable/writable when present, but in some browsers/privacy modes localStorage.getItem/setItem can throw (e.g. SecurityError) and would break the live editor initialization. Wrap the storage access in try/catch and fall back to the default mode when storage is unavailable.

Suggested change
const stored = window.localStorage ? window.localStorage.getItem(STORAGE_KEY) : null;
return stored === "mermaid-2d" ? "mermaid-2d" : "isometric-3d";
}
function persistViewMode(mode) {
if (window.localStorage) {
window.localStorage.setItem(STORAGE_KEY, mode);
try {
const stored = window.localStorage ? window.localStorage.getItem(STORAGE_KEY) : null;
return stored === "mermaid-2d" ? "mermaid-2d" : "isometric-3d";
} catch (error) {
return "isometric-3d";
}
}
function persistViewMode(mode) {
try {
if (window.localStorage) {
window.localStorage.setItem(STORAGE_KEY, mode);
}
} catch (error) {

Copilot uses AI. Check for mistakes.
Comment thread book/src/visualize.md
Comment on lines +122 to +128
```rhai
fn verify_result() -> match_disposition
match result.disposition => Disposition::Unrecoverable -> halt_pipeline
match result.disposition => Disposition::Recoverable -> repair_and_retry
match result.disposition => Disposition::Advisory -> record_note
fn repair_and_retry() -> requeue_validation
```
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The “Match-Style Disposition Routing” sample includes fn verify_result() -> match_disposition, but the match-arm DSL here (match result.disposition => …) generates a separate match node id derived from the expression (match_result_disposition). As a result the rendered graph will contain an unconnected match_disposition step plus a disconnected match result.disposition diamond. Update the sample (or the DSL/ID scheme) so the match node can be reached from the pipeline edge and the example renders as a single connected flow.

Copilot uses AI. Check for mistakes.
1. localStorage try/catch (rhai-live.js): wrap getItem/setItem in
   try/catch so SecurityError in Firefox private mode or iOS Safari
   privacy settings does not break live editor initialization.

2. Disconnected match node (visualize.md, match-visualization-plan.md):
   the parser generates the match node ID as `match_` + sanitize_id(expr),
   so `match result.disposition` → `match_result_disposition`. Samples
   that used `fn verify_result() -> match_disposition` produced an
   unreachable orphan node. Updated all samples and the documentation
   guidance to use the full sanitized form.

3. Misleading docstring (parser.rs): `parse()` returns Graph (never
   Option). Updated the doc comment to say "returns an empty Graph"
   rather than "Returns None".

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@promptexecutionerr promptexecutionerr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed all three review comments in commit 0cf7c7f:

  1. localStorage SecurityError (rhai-live.js): wrapped both getItem and setItem in try/catch with isometric-3d as the safe fallback. Matches the suggested fix exactly.

  2. Disconnected match node (visualize.md, match-visualization-plan.md): the parser generates match node IDs as match_ + sanitize_id(expr), so match result.dispositionmatch_result_disposition. Updated both samples and the documentation guidance. Also updated the 'stable example names' section in the plan doc to explain the derivation rule so authors don't make the same mistake.

  3. Misleading docstring (parser.rs, suppressed comment): fixed Returns None → `Returns an empty `Graph to match the actual return type.

@elasticdotventures elasticdotventures merged commit cf10b59 into main Apr 21, 2026
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants