Created
March 2, 2025 23:21
-
-
Save SoMaCoSF/12292c34627b7baa4897be3d4f04fc1d to your computer and use it in GitHub Desktop.
mermaid to svg script, run within terminal in Composer/vscode (mcp next)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Mermaid to SVG Converter | |
A PowerShell-based utility to convert Mermaid diagram code to SVG files with a text-based user interface. | |
## Overview | |
This tool allows you to create, edit, and convert Mermaid diagram code to SVG files without leaving the terminal. It provides a simple text-based UI for managing and converting your diagrams. | |
 | |
## Features | |
- Interactive text-based UI with navigable menus | |
- Create and edit Mermaid diagrams directly in the terminal | |
- Load existing Mermaid code from files | |
- Convert Mermaid code to SVG using: | |
- Local Mermaid CLI (if installed) | |
- Web-based API fallback (requires internet connection) | |
- Customize output directory | |
- Built-in dependency checker | |
- Simple SVG preview screen | |
## Prerequisites | |
For optimal experience with local rendering: | |
- [Node.js](https://nodejs.org/) | |
- [Mermaid CLI](https://github.com/mermaid-js/mermaid-cli): Install with `npm install -g @mermaid-js/mermaid-cli` | |
The script will automatically fall back to using the Mermaid.ink web API if local dependencies are not available (requires internet connection). | |
## Installation | |
1. Download the `mermaid_to_svg.ps1` script | |
2. Ensure PowerShell execution policy allows running the script | |
```powershell | |
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser | |
``` | |
## Usage | |
### Basic Usage | |
```powershell | |
.\mermaid_to_svg.ps1 | |
``` | |
### Specify Output Directory | |
```powershell | |
.\mermaid_to_svg.ps1 -OutputPath "C:\Diagrams" | |
``` | |
## How to Use | |
1. Run the script using one of the commands above | |
2. Navigate through the main menu using keyboard input: | |
- **1** - Create a new diagram | |
- **2** - Load Mermaid code from a file | |
- **3** - Change the output directory | |
- **4** - Check for dependencies | |
- **5** - Exit | |
### Creating/Editing Diagrams | |
1. Select option **1** or **2** from the main menu | |
2. In the editor screen: | |
- Press **E** to enter edit mode | |
- Type or paste your Mermaid code | |
- Type **END** on a new line when finished | |
- Navigate buttons with arrow keys | |
- Press **Enter** to select a button | |
### Example Diagram Code | |
``` | |
flowchart TD | |
A[Start] --> B{Is it working?} | |
B -->|Yes| C[Great!] | |
B -->|No| D[Debug] | |
D --> B | |
``` | |
## Limitations | |
- The SVG viewer is text-based and does not show the actual SVG content | |
- Some complex Mermaid diagrams may not render correctly with the web API fallback | |
## Troubleshooting | |
If you encounter issues: | |
1. Run the dependency checker (option 4) to verify your setup | |
2. Ensure you have an internet connection if using the web API fallback | |
3. Check that your Mermaid code syntax is valid | |
## License | |
MIT | |
## Acknowledgements | |
- [Mermaid.js](https://mermaid.js.org/) - JavaScript based diagramming and charting tool | |
- [Mermaid CLI](https://github.com/mermaid-js/mermaid-cli) - Command line interface for Mermaid | |
- [Mermaid.ink](https://mermaid.ink/) - Web service for rendering Mermaid diagrams |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
Converts Mermaid diagram code to SVG with a text-based UI | |
.DESCRIPTION | |
This PowerShell script provides a menu-driven interface to convert Mermaid diagram code to SVG files | |
using either the Mermaid CLI (if installed) or the Mermaid Live Editor API. | |
.PARAMETER OutputPath | |
Path to save the SVG file (default: current directory) | |
.EXAMPLE | |
.\mermaid_to_svg.ps1 | |
.\mermaid_to_svg.ps1 -OutputPath "C:\Diagrams" | |
#> | |
param( | |
[string]$OutputPath = "" | |
) | |
# Initialize default values | |
if ([string]::IsNullOrEmpty($OutputPath)) { $OutputPath = (Get-Location).Path } | |
# Function to check if Node.js and Mermaid CLI are installed | |
function Test-MermaidCLI { | |
try { | |
$nodeVersion = node --version | |
$mmdcVersion = mmdc --version 2>$null | |
return $true | |
} | |
catch { | |
return $false | |
} | |
} | |
# Function to convert Mermaid to SVG using Mermaid CLI | |
function Convert-MermaidToSVG-CLI { | |
param( | |
[string]$MermaidCode, | |
[string]$OutputFile | |
) | |
$tempFile = Join-Path $env:TEMP "temp_mermaid.mmd" | |
$MermaidCode | Out-File -FilePath $tempFile -Encoding utf8 | |
try { | |
mmdc -i $tempFile -o $OutputFile | |
return $true | |
} | |
catch { | |
Write-Host "Error using Mermaid CLI: $_" -ForegroundColor Red | |
return $false | |
} | |
finally { | |
if (Test-Path $tempFile) { | |
Remove-Item $tempFile -Force | |
} | |
} | |
} | |
# Function to convert Mermaid to SVG using web API | |
function Convert-MermaidToSVG-API { | |
param( | |
[string]$MermaidCode, | |
[string]$OutputFile | |
) | |
try { | |
# Encode the Mermaid code for URL | |
$encodedMermaid = [System.Web.HttpUtility]::UrlEncode($MermaidCode) | |
# Use mermaid.ink service | |
$url = "https://mermaid.ink/svg/$encodedMermaid" | |
# Download the SVG | |
Invoke-WebRequest -Uri $url -OutFile $OutputFile | |
return $true | |
} | |
catch { | |
Write-Host "Error using Mermaid web API: $_" -ForegroundColor Red | |
return $false | |
} | |
} | |
# Function to display ASCII button | |
function Show-Button { | |
param( | |
[string]$Text, | |
[bool]$Selected = $false | |
) | |
if ($Selected) { | |
Write-Host " [" -NoNewline | |
Write-Host $Text -NoNewline -ForegroundColor Black -BackgroundColor White | |
Write-Host "] " -NoNewline | |
} | |
else { | |
Write-Host " [ " -NoNewline | |
Write-Host $Text -NoNewline | |
Write-Host " ] " -NoNewline | |
} | |
} | |
# Function to display a simple ASCII viewer for SVG | |
function Show-SVGViewer { | |
param( | |
[string]$SVGPath | |
) | |
$width = 60 | |
$height = 15 | |
Clear-Host | |
# Draw top border | |
Write-Host "╔" -NoNewline | |
Write-Host ("═" * ($width - 2)) -NoNewline | |
Write-Host "╗" | |
# Draw title | |
$title = " SVG Viewer: $(Split-Path $SVGPath -Leaf) " | |
$padding = [Math]::Floor(($width - $title.Length) / 2) | |
Write-Host "║" -NoNewline | |
Write-Host (" " * $padding) -NoNewline | |
Write-Host $title -NoNewline -ForegroundColor Cyan | |
Write-Host (" " * ($width - $padding - $title.Length - 2)) -NoNewline | |
Write-Host "║" | |
# Draw separator | |
Write-Host "╠" -NoNewline | |
Write-Host ("═" * ($width - 2)) -NoNewline | |
Write-Host "╣" | |
# Draw content area | |
for ($i = 0; $i -lt $height; $i++) { | |
Write-Host "║" -NoNewline | |
if ($i -eq [Math]::Floor($height / 2)) { | |
$message = " SVG created successfully! " | |
$padding = [Math]::Floor(($width - $message.Length) / 2) | |
Write-Host (" " * $padding) -NoNewline | |
Write-Host $message -NoNewline -ForegroundColor Green | |
Write-Host (" " * ($width - $padding - $message.Length - 2)) -NoNewline | |
} | |
elseif ($i -eq [Math]::Floor($height / 2) + 2) { | |
$message = " Opening in default viewer... " | |
$padding = [Math]::Floor(($width - $message.Length) / 2) | |
Write-Host (" " * $padding) -NoNewline | |
Write-Host $message -NoNewline -ForegroundColor Yellow | |
Write-Host (" " * ($width - $padding - $message.Length - 2)) -NoNewline | |
} | |
else { | |
Write-Host (" " * ($width - 2)) -NoNewline | |
} | |
Write-Host "║" | |
} | |
# Draw bottom border | |
Write-Host "╚" -NoNewline | |
Write-Host ("═" * ($width - 2)) -NoNewline | |
Write-Host "╝" | |
Write-Host | |
Write-Host "Press any key to continue..." -ForegroundColor DarkGray | |
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") | |
} | |
# Function to display the main menu | |
function Show-MainMenu { | |
Clear-Host | |
Write-Host "╔════════════════════════════════════════════════════════╗" -ForegroundColor Cyan | |
Write-Host "║ MERMAID TO SVG CONVERTER ║" -ForegroundColor Cyan | |
Write-Host "╚════════════════════════════════════════════════════════╝" -ForegroundColor Cyan | |
Write-Host | |
Write-Host "Current Settings:" -ForegroundColor Yellow | |
Write-Host " Output Path: $OutputPath" | |
Write-Host | |
Write-Host "1. Create New Diagram" | |
Write-Host "2. Load Mermaid Code from File" | |
Write-Host "3. Change Output Path" | |
Write-Host "4. Check Dependencies" | |
Write-Host "5. Exit" | |
Write-Host | |
$choice = Read-Host "Enter your choice (1-5)" | |
return $choice | |
} | |
# Function to display the editor interface | |
function Show-MermaidEditor { | |
param( | |
[string[]]$InitialCode = @() | |
) | |
$mermaidCode = $InitialCode | |
$selectedButton = 0 # 0 = Submit, 1 = Clear, 2 = Cancel | |
$buttons = @("Submit", "Clear", "Cancel") | |
$editing = $true | |
while ($editing) { | |
Clear-Host | |
Write-Host "╔════════════════════════════════════════════════════════╗" -ForegroundColor Cyan | |
Write-Host "║ MERMAID CODE EDITOR ║" -ForegroundColor Cyan | |
Write-Host "╚════════════════════════════════════════════════════════╝" -ForegroundColor Cyan | |
Write-Host | |
Write-Host "Enter your Mermaid diagram code below:" -ForegroundColor Yellow | |
Write-Host "Use the arrow keys to navigate and Enter to submit." -ForegroundColor Yellow | |
Write-Host | |
# Display the code box | |
Write-Host "┌" + ("─" * 58) + "┐" | |
if ($mermaidCode.Count -eq 0) { | |
Write-Host "│" -NoNewline | |
Write-Host " <Enter your Mermaid code here> " -NoNewline -ForegroundColor DarkGray | |
Write-Host (" " * 28) -NoNewline | |
Write-Host "│" | |
} | |
else { | |
foreach ($line in $mermaidCode) { | |
$displayLine = if ($line.Length -gt 56) { $line.Substring(0, 53) + "..." } else { $line } | |
$padding = 58 - $displayLine.Length | |
Write-Host "│ " -NoNewline | |
Write-Host $displayLine -NoNewline | |
Write-Host (" " * $padding) -NoNewline | |
Write-Host "│" | |
} | |
} | |
Write-Host "└" + ("─" * 58) + "┘" | |
Write-Host | |
# Display buttons | |
Write-Host " " -NoNewline | |
for ($i = 0; $i -lt $buttons.Length; $i++) { | |
Show-Button -Text $buttons[$i] -Selected ($i -eq $selectedButton) | |
Write-Host " " -NoNewline | |
} | |
Write-Host | |
Write-Host | |
Write-Host "Press 'E' to edit, arrow keys to navigate, Enter to select" -ForegroundColor DarkGray | |
# Get key input | |
$key = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") | |
switch ($key.VirtualKeyCode) { | |
37 { | |
# Left arrow | |
$selectedButton = ($selectedButton - 1) % $buttons.Length | |
if ($selectedButton -lt 0) { $selectedButton = $buttons.Length - 1 } | |
} | |
39 { | |
# Right arrow | |
$selectedButton = ($selectedButton + 1) % $buttons.Length | |
} | |
69 { | |
# E key | |
# Edit mode | |
Clear-Host | |
Write-Host "Enter/paste your Mermaid code below." -ForegroundColor Yellow | |
Write-Host "Type 'END' on a new line when finished." -ForegroundColor Yellow | |
Write-Host | |
$newCode = @() | |
$line = "" | |
do { | |
$line = Read-Host | |
if ($line -ne "END") { | |
$newCode += $line | |
} | |
} while ($line -ne "END") | |
if ($newCode.Count -gt 0) { | |
$mermaidCode = $newCode | |
} | |
} | |
13 { | |
# Enter key | |
switch ($selectedButton) { | |
0 { | |
# Submit | |
if ($mermaidCode.Count -gt 0) { | |
$editing = $false | |
return $mermaidCode | |
} | |
else { | |
Write-Host "Please enter some Mermaid code first." -ForegroundColor Red | |
Start-Sleep -Seconds 2 | |
} | |
} | |
1 { | |
# Clear | |
$mermaidCode = @() | |
} | |
2 { | |
# Cancel | |
return $null | |
} | |
} | |
} | |
} | |
} | |
return $mermaidCode | |
} | |
# Function to load Mermaid code from file | |
function Load-MermaidFromFile { | |
$filePath = Read-Host "Enter path to Mermaid file (.mmd, .txt)" | |
if (-not (Test-Path $filePath)) { | |
Write-Host "File not found: $filePath" -ForegroundColor Red | |
Start-Sleep -Seconds 2 | |
return $null | |
} | |
try { | |
$content = Get-Content -Path $filePath -Raw | |
return $content -split "`n" | |
} | |
catch { | |
Write-Host "Error reading file: $_" -ForegroundColor Red | |
Start-Sleep -Seconds 2 | |
return $null | |
} | |
} | |
# Function to change output path | |
function Set-OutputDirectory { | |
$newPath = Read-Host "Enter new output path (current: $OutputPath)" | |
if ([string]::IsNullOrEmpty($newPath)) { | |
return $OutputPath | |
} | |
if (Test-Path $newPath -PathType Container) { | |
return $newPath | |
} | |
else { | |
$createDir = Read-Host "Directory doesn't exist. Create it? (y/n)" | |
if ($createDir -eq "y") { | |
try { | |
New-Item -ItemType Directory -Path $newPath -Force | Out-Null | |
return $newPath | |
} | |
catch { | |
Write-Host "Error creating directory: $_" -ForegroundColor Red | |
Start-Sleep -Seconds 2 | |
return $OutputPath | |
} | |
} | |
else { | |
return $OutputPath | |
} | |
} | |
} | |
# Function to check dependencies | |
function Check-Dependencies { | |
Clear-Host | |
Write-Host "╔════════════════════════════════════════════════════════╗" -ForegroundColor Cyan | |
Write-Host "║ DEPENDENCY CHECKER ║" -ForegroundColor Cyan | |
Write-Host "╚════════════════════════════════════════════════════════╝" -ForegroundColor Cyan | |
Write-Host | |
# Check for Node.js | |
Write-Host "Checking for Node.js..." -NoNewline | |
try { | |
$nodeVersion = node --version | |
Write-Host " FOUND" -ForegroundColor Green | |
Write-Host " Version: $nodeVersion" | |
} | |
catch { | |
Write-Host " NOT FOUND" -ForegroundColor Red | |
Write-Host " Node.js is required for local rendering. Install from https://nodejs.org/" | |
} | |
# Check for Mermaid CLI | |
Write-Host "Checking for Mermaid CLI..." -NoNewline | |
try { | |
$mmdcVersion = mmdc --version 2>$null | |
Write-Host " FOUND" -ForegroundColor Green | |
Write-Host " Version: $mmdcVersion" | |
} | |
catch { | |
Write-Host " NOT FOUND" -ForegroundColor Red | |
Write-Host " Install with: npm install -g @mermaid-js/mermaid-cli" | |
} | |
# Check for internet connection (for API fallback) | |
Write-Host "Checking internet connection..." -NoNewline | |
try { | |
$webRequest = Invoke-WebRequest -Uri "https://mermaid.ink" -UseBasicParsing -TimeoutSec 5 | |
Write-Host " CONNECTED" -ForegroundColor Green | |
} | |
catch { | |
Write-Host " NOT CONNECTED" -ForegroundColor Yellow | |
Write-Host " Internet connection required for API fallback if CLI is not available." | |
} | |
Write-Host | |
Write-Host "Press any key to continue..." -ForegroundColor DarkGray | |
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") | |
} | |
# Main function | |
function Start-MermaidConverter { | |
$exit = $false | |
while (-not $exit) { | |
$choice = Show-MainMenu | |
switch ($choice) { | |
"1" { | |
# Create New Diagram | |
$mermaidCode = Show-MermaidEditor | |
if ($null -ne $mermaidCode -and $mermaidCode.Count -gt 0) { | |
# Join the lines | |
$mermaidCodeText = $mermaidCode -join "`n" | |
# Get output filename | |
$defaultFilename = "mermaid_diagram_$(Get-Date -Format 'yyyyMMdd_HHmmss').svg" | |
$outputFilename = Read-Host "Enter output filename (default: $defaultFilename)" | |
if ([string]::IsNullOrEmpty($outputFilename)) { | |
$outputFilename = $defaultFilename | |
} | |
if (-not $outputFilename.EndsWith(".svg")) { | |
$outputFilename += ".svg" | |
} | |
$outputFile = Join-Path $OutputPath $outputFilename | |
# Ensure output directory exists | |
$outputDir = Split-Path -Path $outputFile -Parent | |
if (-not (Test-Path $outputDir)) { | |
New-Item -ItemType Directory -Path $outputDir | Out-Null | |
} | |
# Try to convert using available methods | |
Write-Host "Converting Mermaid code to SVG..." -ForegroundColor Cyan | |
$success = $false | |
# First try using Mermaid CLI if available | |
if (Test-MermaidCLI) { | |
Write-Host "Using Mermaid CLI..." -ForegroundColor Green | |
$success = Convert-MermaidToSVG-CLI -MermaidCode $mermaidCodeText -OutputFile $outputFile | |
} | |
# If CLI failed or not available, try web API | |
if (-not $success) { | |
Write-Host "Using Mermaid web API..." -ForegroundColor Yellow | |
# Load HttpUtility for URL encoding | |
Add-Type -AssemblyName System.Web | |
$success = Convert-MermaidToSVG-API -MermaidCode $mermaidCodeText -OutputFile $outputFile | |
} | |
if ($success) { | |
# Show the SVG viewer | |
Show-SVGViewer -SVGPath $outputFile | |
# Open the file | |
Invoke-Item $outputFile | |
} | |
else { | |
Write-Host "Failed to convert Mermaid code to SVG." -ForegroundColor Red | |
Start-Sleep -Seconds 2 | |
} | |
} | |
} | |
"2" { | |
# Load Mermaid Code from File | |
$loadedCode = Load-MermaidFromFile | |
if ($null -ne $loadedCode) { | |
$mermaidCode = Show-MermaidEditor -InitialCode $loadedCode | |
if ($null -ne $mermaidCode -and $mermaidCode.Count -gt 0) { | |
# Process the same as option 1 | |
# (Code duplicated for clarity, could be refactored) | |
$mermaidCodeText = $mermaidCode -join "`n" | |
$defaultFilename = "mermaid_diagram_$(Get-Date -Format 'yyyyMMdd_HHmmss').svg" | |
$outputFilename = Read-Host "Enter output filename (default: $defaultFilename)" | |
if ([string]::IsNullOrEmpty($outputFilename)) { | |
$outputFilename = $defaultFilename | |
} | |
if (-not $outputFilename.EndsWith(".svg")) { | |
$outputFilename += ".svg" | |
} | |
$outputFile = Join-Path $OutputPath $outputFilename | |
if (-not (Test-Path (Split-Path -Path $outputFile -Parent))) { | |
New-Item -ItemType Directory -Path (Split-Path -Path $outputFile -Parent) | Out-Null | |
} | |
$success = $false | |
if (Test-MermaidCLI) { | |
$success = Convert-MermaidToSVG-CLI -MermaidCode $mermaidCodeText -OutputFile $outputFile | |
} | |
if (-not $success) { | |
Add-Type -AssemblyName System.Web | |
$success = Convert-MermaidToSVG-API -MermaidCode $mermaidCodeText -OutputFile $outputFile | |
} | |
if ($success) { | |
Show-SVGViewer -SVGPath $outputFile | |
Invoke-Item $outputFile | |
} | |
else { | |
Write-Host "Failed to convert Mermaid code to SVG." -ForegroundColor Red | |
Start-Sleep -Seconds 2 | |
} | |
} | |
} | |
} | |
"3" { | |
# Change Output Path | |
$OutputPath = Set-OutputDirectory | |
} | |
"4" { | |
# Check Dependencies | |
Check-Dependencies | |
} | |
"5" { | |
# Exit | |
$exit = $true | |
} | |
default { | |
Write-Host "Invalid choice. Please try again." -ForegroundColor Red | |
Start-Sleep -Seconds 1 | |
} | |
} | |
} | |
} | |
# Start the application | |
Start-MermaidConverter |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment