Last active
May 20, 2025 17:56
-
-
Save bobbae/e66b7b1004705bee9ce9f130acaec9ff to your computer and use it in GitHub Desktop.
mermaid js diagram renderer
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
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Mermaid Diagram Renderer</title> | |
| <style> | |
| body { | |
| font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; | |
| margin: 0; | |
| padding: 20px; | |
| background-color: #f0f2f5; | |
| color: #333; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| } | |
| h1 { | |
| text-align: center; | |
| color: #1a237e; /* Dark blue */ | |
| margin-bottom: 20px; | |
| } | |
| .controls { | |
| background-color: #fff; | |
| padding: 20px; | |
| border-radius: 8px; | |
| box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); | |
| margin-bottom: 20px; | |
| width: 90%; | |
| max-width: 700px; | |
| box-sizing: border-box; | |
| } | |
| textarea { | |
| width: 100%; /* Full width of parent .controls */ | |
| height: 200px; | |
| padding: 10px; | |
| font-family: monospace; | |
| font-size: 14px; | |
| border: 1px solid #ccc; | |
| border-radius: 4px; | |
| margin-bottom: 15px; | |
| box-sizing: border-box; | |
| resize: vertical; | |
| } | |
| button { | |
| display: block; | |
| width: 100%; /* Full width of parent .controls */ | |
| padding: 12px 20px; | |
| font-size: 16px; | |
| font-weight: bold; | |
| color: white; | |
| background-color: #28a745; /* Green */ | |
| border: none; | |
| border-radius: 4px; | |
| cursor: pointer; | |
| transition: background-color 0.2s ease-in-out; | |
| } | |
| button:hover { | |
| background-color: #218838; /* Darker green */ | |
| } | |
| .mermaid { | |
| margin-top: 20px; | |
| padding: 20px; | |
| border: 1px solid #e0e0e0; | |
| border-radius: 8px; | |
| background-color: #ffffff; | |
| box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| min-height: 100px; | |
| width: 90%; | |
| max-width: 700px; | |
| box-sizing: border-box; | |
| } | |
| .mermaid svg { | |
| max-width: 100%; /* Ensure SVG is responsive */ | |
| height: auto; /* Maintain aspect ratio */ | |
| } | |
| #err { | |
| margin-top: 15px; | |
| padding: 10px 15px; | |
| background-color: #f8d7da; /* Light red for errors */ | |
| color: #721c24; /* Dark red text for errors */ | |
| border: 1px solid #f5c6cb; | |
| border-radius: 4px; | |
| white-space: pre-wrap; | |
| word-break: break-all; | |
| width: 90%; /* Match .controls and .mermaid width */ | |
| max-width: 700px; /* Match .controls and .mermaid max-width */ | |
| box-sizing: border-box; | |
| } | |
| #err:empty { | |
| display: none; /* Hide error box if empty */ | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <h1>Mermaid Diagram Renderer</h1> | |
| <div class="controls"> | |
| <textarea> | |
| mermaid | |
| graph LR | |
| subgraph Core Layer | |
| C1[Core Router 1] | |
| C2[Core Router 2] | |
| end | |
| subgraph Distribution Layer | |
| D1[Dist. Switch 1] | |
| D2[Dist. Switch 2] | |
| D3[Dist. Switch 3] | |
| end | |
| subgraph Access Layer A | |
| A1[Access Switch 1] | |
| A2[Access Switch 2] | |
| A3[Access Switch 3] | |
| A4[Access Switch 4] | |
| end | |
| subgraph Access Layer B | |
| B1[Access Switch 5] | |
| B2[Access Switch 6] | |
| B3[Access Switch 7] | |
| B4[Access Switch 8] | |
| end | |
| C1 --> D1 & D2 | |
| C2 --> D2 & D3 | |
| D1 --> A1 & A2 | |
| D2 --> A2 & A3 & B1 | |
| D3 --> A4 & B2 & B3 & B4 | |
| style C1 fill:#f9f,stroke:#333,stroke-width:2px | |
| style C2 fill:#f9f,stroke:#333,stroke-width:2px | |
| style D1 fill:#ccf,stroke:#333,stroke-width:2px | |
| style D2 fill:#ccf,stroke:#333,stroke-width:2px | |
| style D3 fill:#ccf,stroke:#333,stroke-width:2px | |
| </textarea> | |
| <button onclick="mermaidDraw()">Render Diagram</button> | |
| </div> | |
| <div class="mermaid"></div> | |
| <pre id="err"></pre> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/mermaid/10.9.0/mermaid.min.js"></script> | |
| <script> | |
| mermaid.initialize({ | |
| startOnLoad: true | |
| }); | |
| eleM = document.querySelector('.mermaid'); | |
| eleE = document.querySelector('#err'); | |
| setTimeout(mermaidDraw, 200); | |
| async function mermaidDraw() { | |
| try { | |
| eleE.innerHTML = ''; // Clear previous errors | |
| graphDefinition = await mermaidEval('LocalFile.md'); | |
| const { | |
| svg | |
| } = await mermaid.render('graphDiv', graphDefinition); | |
| eleM.innerHTML = svg; | |
| } catch (err) { | |
| if (err instanceof ReferenceError) { | |
| varname = err.message.split(' ')[0]; | |
| window[varname] = varname; | |
| setTimeout(mermaidDraw, 0); | |
| } | |
| console.error(err); | |
| eleE.insertAdjacentHTML('beforeend', `🚫 ${err.message}\n`); | |
| } | |
| }; | |
| async function mermaidEval(url) { | |
| text = document.querySelector('textarea').value; | |
| if (!text.match(/^[a-zA-Z]/)) { | |
| // markdown ```mermaid, remove first and last line | |
| text = text.split('\n').slice(1, -1).join('\n'); | |
| } | |
| text = text.replace(/"`.*?`"/g, function(match) { | |
| return eval(match.slice(1, -1)); | |
| }); | |
| text = text.replace(/"\{.*?\}"/g, function(match) { | |
| return eval(match.slice(1, -1)); | |
| }); | |
| return text; | |
| } | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment