-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmermaid.html
More file actions
333 lines (308 loc) · 14.5 KB
/
mermaid.html
File metadata and controls
333 lines (308 loc) · 14.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Character encoding -->
<meta charset="UTF-8">
<!-- Title of the page -->
<title>Mermaid Chart Viewer</title>
<!-- Google Fonts -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap">
<!-- Prism.js CSS for syntax highlighting -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.24.1/themes/prism.min.css" rel="stylesheet">
<!-- Prism.js Core -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.24.1/components/prism-core.min.js"></script>
<!-- Mermaid.js for rendering Mermaid charts -->
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
<!-- html2canvas for exporting charts as PNG -->
<script src="https://cdn.jsdelivr.net/npm/html2canvas@1.4.0/dist/html2canvas.min.js"></script>
<!-- Internal CSS styles -->
<style>
/* Container styles */
.container {
max-width: 800px;
margin: 40px auto;
padding: 20px;
background: #f5f5f5; /* Light grey background */
border-radius: 10px;
font-family: 'Roboto', sans-serif;
color: #333; /* Dark grey text color */
}
/* Section styles */
.section {
margin-bottom: 30px;
padding: 10px;
}
/* Button styles */
button {
padding: 12px 25px;
background-color: #007acc;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
transition: background-color 0.3s, transform 0.3s;
}
button:hover {
background-color: #00508f;
transform: scale(1.05);
}
/* Contenteditable div styles */
.contenteditable-div {
width: 100%;
min-height: 200px;
padding: 10px;
border-radius: 5px;
border: 1px solid #ccc; /* Light grey border */
font-family: monospace;
overflow-y: auto;
white-space: pre-wrap;
background-color: #fff; /* White background */
color: #333; /* Dark grey text color */
}
/* Horizontal rule styles */
hr {
border: 0;
height: 1px;
background: #ccc; /* Light grey horizontal rule */
}
/* Import button styles */
.import-button {
margin-bottom: 10px;
}
/* Syntax highlighting styles */
/* Define colors for different syntax tokens */
.token.comment { color: #6a737d; } /* Comments */
.token.keyword { color: #d73a49; font-weight: bold; } /* Keywords */
.token.arrow { color: #005cc5; } /* Arrows */
.token.selector { color: #6f42c1; } /* Selectors */
.token.class { color: #005cc5; } /* Classes */
.token.event { color: #6f42c1; font-weight: bold; } /* Events */
.token.direction { color: #005cc5; font-weight: bold; } /* Directions */
.token.style { color: #6f42c1; font-weight: bold; } /* Styles */
.token.string { color: #032f62; } /* Strings */
.token.link { color: #d73a49; font-weight: bold; } /* Link labels */
.token.linkTarget { color: #005cc5; font-weight: bold; } /* Link targets */
.token.linkText { color: #005cc5; font-weight: bold; } /* Link text */
.token.text { color: #333; } /* Regular text */
.token.number { color: #005cc5; } /* Numbers */
.token.operator { color: #d73a49; } /* Operators */
.token.shape { color: #6f42c1; font-weight: bold; } /* Shape types */
.token.decorator { color: #005cc5; font-weight: bold; } /* Decorators */
.token.flowControl { color: #d73a49; font-weight: bold; } /* Flow control */
.token.color { color: #6f42c1; font-weight: bold; } /* Colors */
/* Adjusted connector color for better visibility */
.token.arrow { color: #6f42c1; } /* Arrows */
/* Customization for 'task' keyword */
.token.task { color: #228B22; font-weight: bold; } /* Tasks */
/* Customization for 'gateway' keyword */
.token.gateway { color: #FFA500; font-weight: bold; } /* Gateways */
/* Customization for 'first and last items' */
.token.firstLastItems { color: #d73a49; } /* Same color as other keywords */
</style>
<!-- Custom Prism language for Mermaid -->
<script>
Prism.languages.mermaid = {
'comment': /#.*/,
'keyword': /\b(?:graph|subgraph|end|classDef|click|dir|TB|LR|TD|BT|clickHandler|link|on|note|style)\b/,
'arrow': /-->/,
'selector': /\b(?:class|node(?:\.|\s+style)\s*:\s*([\w-]+))\b/,
'event': /\b(?:click|dblclick)\b/,
'direction': /\b(?:TB|LR|TD|BT)\b/,
'style': /\b(?:dotted|solid|dashed)\b/,
'string': /"(?:\\.|[^\\"])*"/,
'link': /\[(.*?)\]/,
'linkTarget': /\((.*?)\)/,
'linkText': /\|(.*?)\|/,
'text': /\w+(?=")/,
'number': /\b\d+\b/,
'operator': /=/,
'shape': /\b(?:box|circle|ellipse|diamond|hexagon|rect|roundrect|stadium|cylinder|line|tab|cloud)\b/,
'decorator': /\b(?:start|end|left|right|link|node)\b/,
'flowControl': /\b(?:if|else|end)\b/,
'color': /\b(?:red|green|blue|orange|purple|pink|yellow|black|white|gray|darkred|darkgreen|darkblue|darkorange|darkpurple|darkpink|darkyellow|darkgray)\b/,
'task': /\b(?:task)\b/, // Added 'task' keyword
'gateway': /\b(?:gateway)\b/, // Changed to 'gateway' keyword
'firstLastItems': /\b(?:Start|SaveFile)\b/ // Added 'first and last items' keyword
};
// Function to apply Prism.js syntax highlighting to a contenteditable div
function highlightCode() {
// Get the contenteditable div element
const contentDiv = document.getElementById('mermaid-code');
if (contentDiv) {
// Get the text content and trim it
const text = contentDiv.innerText.trim();
// Highlight the text using Prism.js and update the innerHTML of the div
const highlightedText = Prism.highlight(text, Prism.languages.mermaid, 'mermaid');
contentDiv.innerHTML = highlightedText;
}
}
// Function to render the Mermaid chart
function renderMermaidCode() {
// Get the contenteditable div and the container for the chart
const contentDiv = document.getElementById('mermaid-code');
const container = document.querySelector('.mermaid');
if (container && contentDiv) {
// Get the Mermaid code from the div
const mermaidCode = contentDiv.innerText.trim();
// Insert the Mermaid code into the container and render the chart
container.innerHTML = `<div class="mermaid">${mermaidCode}</div>`;
mermaid.contentLoaded();
}
}
let timeoutId;
// Function to handle input events with a delay
function handleInput() {
// Clear the previous timeout
clearTimeout(timeoutId);
// Set a new timeout to execute after a delay
timeoutId = setTimeout(function() {
// Apply syntax highlighting and render the Mermaid chart
highlightCode();
renderMermaidCode();
}, 500);
}
// Event listener for window onload event
window.onload = function() {
// Get the contenteditable div element
const contentDiv = document.getElementById('mermaid-code');
if (contentDiv) {
// Add input event listener to the contenteditable div
contentDiv.addEventListener('input', handleInput);
// Default Mermaid code for demonstration
const defaultMermaidCode = `graph TD;
Start[Open Page] --> PasteMermaid["Paste or Import Mermaid Code into Text Area"];
PasteMermaid --> RenderChart["Render Chart in Container"];
RenderChart --> ExportOptions["Select Export Option"];
ExportOptions --> ExportFormat["Choose Format (SVG/PNG/Mermaid)"];
ExportFormat --> ExportButton["Click Export Button"];
ExportButton --> SaveFile["Save Chart to File"];
PasteMermaid --> |Import from File| ImportMermaid["Click Import Button"];
ImportMermaid --> |Load .mermaid File| PasteMermaid;
`;
// Set the default Mermaid code and trigger input event
contentDiv.innerText = defaultMermaidCode;
handleInput();
}
};
// Function to import Mermaid code from a file
async function importFromFile() {
try {
// Open file picker dialog to select a file
const [fileHandle] = await window.showOpenFilePicker({
types: [
{
description: 'Mermaid Files',
accept: {
'text/plain': ['.mermaid', '.txt'],
},
},
],
});
// Get the selected file and its text content
const file = await fileHandle.getFile();
const text = await file.text();
// Get the contenteditable div element
const contentDiv = document.getElementById('mermaid-code');
if (contentDiv) {
// Set the text content and trigger input event
contentDiv.innerText = text.trim();
handleInput();
}
} catch (error) {
console.error("Error importing file:", error);
}
}
// Function to export the chart as SVG, PNG, or Mermaid code
async function exportChartAs() {
// Get the selected export format
const exportFormat = document.getElementById('export-format').value;
// Get the container for the chart
const container = document.querySelector('.mermaid');
if (container) {
try {
let blob = null;
// Generate a blob based on the export format
if (exportFormat === 'svg') {
blob = new Blob([container.innerHTML], { type: 'image/svg+xml' });
} else if (exportFormat === 'png') {
const canvas = await html2canvas(container);
blob = await new Promise(resolve => canvas.toBlob(resolve, 'image/png'));
} else if (exportFormat === 'mermaid') {
const mermaidCode = document.getElementById('mermaid-code').innerText.trim();
blob = new Blob([mermaidCode], { type: 'text/plain' });
}
if (blob) {
// Open file save dialog to save the exported file
const fileHandle = await window.showSaveFilePicker({
types: [
{
description: `.${exportFormat.toUpperCase()} Files`,
accept: {
[exportFormat === 'svg' ? 'image/svg+xml' : 'image/png']: [`.${exportFormat}`],
},
},
],
});
// Create a writable stream and write the blob to the file
const writableStream = await fileHandle.createWritable();
await writableStream.write(blob);
await writableStream.close();
}
} catch (error) {
console.error("Error exporting chart:", error);
}
}
}
</script>
</head>
<body>
<!-- Main container -->
<div class="container">
<!-- Import section -->
<div class="section import-section">
<!-- Import chart header -->
<h2>Import Chart</h2>
<!-- Contenteditable div for Mermaid code -->
<div id="mermaid-code" class="contenteditable-div" contenteditable="true">
<!-- Default content -->
graph TD;
Start[Open Page] --> |1| PasteMermaid["Paste or Import Mermaid Code into Text Area"];
PasteMermaid --> |2| RenderChart["Render Chart in Container"];
RenderChart --> |3| ExportOptions["Select Export Option"];
ExportOptions --> |4| ExportFormat["Choose Format (SVG/PNG/Mermaid)"];
graph TD;
Start[Open Page] --> PasteMermaid["Paste or Import Mermaid Code into Text Area"];
PasteMermaid -->RenderChart["Render Chart in Container"];
RenderChart --> ExportOptions["Select Export Option"];
ExportOptions --> ExportFormat["Choose Format (SVG/PNG/Mermaid)"];
ExportFormat -->ExportButton["Click Export Button"];
ExportButton -->SaveFile["Save Chart to File"];
PasteMermaid --> |Import from File| ImportMermaid["Click Import Button"];
ImportMermaid --> |Load .mermaid File| PasteMermaid;
</div>
<!-- Buttons for import and export -->
<div>
<button class="import-button" onclick="importFromFile()">Import from File</button>
<button onclick="exportChartAs()">Export Chart</button>
<!-- Dropdown for export format selection -->
<select id="export-format">
<option value="svg">SVG</option>
<option value="png">PNG</option>
<option value="mermaid">Mermaid Code</option>
</select>
</div>
</div>
<!-- Horizontal rule -->
<hr/>
<!-- Export section -->
<div class="section export-section">
<!-- Mermaid chart header -->
<h2>Mermaid Chart</h2>
<!-- Container for the rendered chart -->
<div class="mermaid">
<!-- Placeholder for the rendered chart -->
</div>
</div>
</div>
</body>
</html>