1<script> 2 import { onMount } from 'svelte'; 3 import { codeStore, updateCode, updateCodeStore } from '../code-store.js'; 4 import Editor from '../components/Editor.svelte'; 5 import Config from '../components/Config.svelte'; 6 import View from '../components/View.svelte'; 7 import Card from '../components/Card.svelte'; 8 import Tag from '../components/Tag.svelte'; 9 import Links from '../components/Links.svelte'; 10 import { fromUrl } from '../code-store.js'; 11 import pkg from '@mermaid/package.json'; 12 import moment from 'moment'; 13 export let mermaidVersion = pkg.version; 14 let historyList = []; 15 onMount(async () => { 16 ga('send', 'pageview'); 17 ga('send', 'event', 'version', mermaidVersion, mermaidVersion); 18 19 const historyListKey = '_mermaid_history_'; 20 historyList = JSON.parse(localStorage.getItem(historyListKey) || '[]'); 21 let hisCode = 22 historyList.length > 0 ? historyList[historyList.length - 1] : null; 23 24 if (params.data) { 25 fromUrl(params.data); 26 } else if (hisCode) { 27 updateCodeStore({ 28 code: hisCode.code, 29 mermaid: {}, 30 updateEditor: true, 31 }); 32 } else { 33 loadSampleDiagram('Flow Chart'); 34 } 35 36 let code = null; 37 codeStore.subscribe((state) => { 38 code = (state && state.code) || code; 39 }); 40 41 setInterval(() => { 42 if (code != hisCode) { 43 //save history 44 historyList.unshift({ 45 time: new Date().toISOString(), 46 code: (hisCode = code), 47 }); 48 if (historyList.length > 10) { 49 historyList.pop(); 50 } 51 localStorage.setItem(historyListKey, JSON.stringify(historyList)); 52 } 53 historyList = historyList; //triggered update 54 }, 1 * 60 * 1000); 55 }); 56 57 export let params = {}; 58 const samples = { 59 'Flow Chart': `graph TD 60 A[Christmas] -->|Get money| B(Go shopping) 61 B --> C{Let me think} 62 C -->|One| D[Laptop] 63 C -->|Two| E[iPhone] 64 C -->|Three| F[fa:fa-car Car]`, 65 'Sequence Diagram': `sequenceDiagram 66 Alice->>+John: Hello John, how are you? 67 Alice->>+John: John, can you hear me? 68 John-->>-Alice: Hi Alice, I can hear you! 69 John-->>-Alice: I feel great! 70 `, 71 'Class Diagram': `classDiagram 72 Animal <|-- Duck 73 Animal <|-- Fish 74 Animal <|-- Zebra 75 Animal : +int age 76 Animal : +String gender 77 Animal: +isMammal() 78 Animal: +mate() 79 class Duck{ 80 +String beakColor 81 +swim() 82 +quack() 83 } 84 class Fish{ 85 -int sizeInFeet 86 -canEat() 87 } 88 class Zebra{ 89 +bool is_wild 90 +run() 91 } 92 `, 93 'State Diagram': `stateDiagram-v2 94 [*] --> Still 95 Still --> [*] 96 Still --> Moving 97 Moving --> Still 98 Moving --> Crash 99 Crash --> [*] 100 `, 101 'Gantt Chart': `gantt 102 title A Gantt Diagram 103 dateFormat YYYY-MM-DD 104 section Section 105 A task :a1, 2014-01-01, 30d 106 Another task :after a1 , 20d 107 section Another 108 Task in sec :2014-01-12 , 12d 109 another task : 24d 110 `, 111 'Pie Chart': `pie title Pets adopted by volunteers 112 "Dogs" : 386 113 "Cats" : 85 114 "Rats" : 15 115 `, 116 'ER Diagram': `erDiagram 117 CUSTOMER }|..|{ DELIVERY-ADDRESS : has 118 CUSTOMER ||--o{ ORDER : places 119 CUSTOMER ||--o{ INVOICE : "liable for" 120 DELIVERY-ADDRESS ||--o{ ORDER : receives 121 INVOICE ||--|{ ORDER : covers 122 ORDER ||--|{ ORDER-ITEM : includes 123 PRODUCT-CATEGORY ||--|{ PRODUCT : contains 124 PRODUCT ||--o{ ORDER-ITEM : "ordered in" 125 `, 126 }; 127 128 function loadSampleDiagram(diagramType) { 129 toUpdateCodeStore(samples[diagramType]); 130 } 131 132 function toUpdateCodeStore(code) { 133 if (!code) return; 134 updateCode(code, true); 135 } 136 137 function relativeTime(t) { 138 return `${moment(t).fromNow()} (${new Date(t).toLocaleString()})`; 139 } 140</script> 141 142<style> 143 #body { 144 font-family: 'Roboto', sans-serif; 145 background-color: #fcfbfc; 146 } 147 #editor-root { 148 display: flex; 149 height: 100%; 150 } 151 #col1 { 152 width: 35%; 153 } 154 #col2 { 155 width: 65%; 156 padding-left: 32px; 157 } 158 #link-root { 159 display: flex; 160 height: fit-content; 161 } 162 #link-col1 { 163 width: 50%; 164 } 165 #link-col2 { 166 width: 50%; 167 padding-left: 32px; 168 } 169 #app-title { 170 font-family: 'Playfair Display', serif; 171 font-size: 32px; 172 font-weight: 700; 173 margin: 0; 174 color: #1e60ab; 175 opacity: 0.8; 176 } 177 #title-container { 178 width: fit-content; 179 margin: 0 auto 8px; 180 } 181 #power { 182 width: 100%; 183 display: flex; 184 justify-content: flex-end; 185 align-items: center; 186 height: 4rem; 187 } 188 #sampleLoader { 189 padding-left: 10px; 190 border-bottom: 1px solid lightgray; 191 } 192 #historyLoaderSubTitle { 193 display: inline-block; 194 color: #33a2c4; 195 font-size: small; 196 font-style: italic; 197 } 198 .button-container { 199 display: flex; 200 align-items: center; 201 flex-direction: row; 202 flex-wrap: wrap; 203 } 204 .button-style { 205 background-color: #a2d9e2; 206 color: #33a2c4; 207 border-radius: 0.25rem; 208 padding: 0.5rem; 209 border: 1px solid #a2d9e2; 210 margin: 0.25rem; 211 } 212 .button-style:hover { 213 background-color: #fff; 214 color: #33a2c4; 215 border: 1px solid #33a2c4; 216 } 217 .button-style:focus { 218 outline: none; 219 } 220 .link-style { 221 text-decoration: none; 222 color: #33a2c4; 223 } 224</style> 225 226<div id="body"> 227 <div id="title-container"> 228 <h1 id="app-title">Mermaid Live Editor</h1> 229 </div> 230 <div id="sampleLoader"> 231 <div class="button-container"> 232 <span id="sampleLoaderTitle"><strong>Diagram presets:</strong></span> 233 {#each Object.keys(samples) as diagramType, i} 234 <button 235 class="button-style" 236 on:click={(e) => loadSampleDiagram(diagramType)}> 237 {diagramType} 238 </button> 239 {/each} 240 </div> 241 </div> 242 <div id="editor-root"> 243 <div id="col1"> 244 <Card title="Code" noPadding="true"> 245 <Editor data={params.data} /> 246 </Card> 247 <Card title="Mermaid Configuration"> 248 <Config /> 249 </Card> 250 </div> 251 <div id="col2"> 252 <Card title="Preview"> 253 <View /> 254 </Card> 255 <div id="link-root"> 256 <div id="link-col1"> 257 <Card title="Editing history"> 258 <span id="historyLoaderSubTitle">Automatically saves once every 259 minute, up to 10 records.</span> 260 <br /> 261 <div id="historyList" class="button-container"> 262 {#if historyList.length > 0} 263 {#each historyList as item, i} 264 <button 265 class="button-style" 266 on:click={(e) => toUpdateCodeStore(item.code)}> 267 {relativeTime(item.time)} 268 </button> 269 {/each} 270 {:else}No records.{/if} 271 </div> 272 </Card> 273 <Card title="Links"> 274 <div class="button-container"> 275 <button class="button-style"> 276 <a 277 href="https://mermaid-js.github.io/mermaid" 278 target="_blank" 279 class="link-style"> 280 Mermaid Documentation 281 </a> 282 </button> 283 <button class="button-style"> 284 <a 285 href="https://github.com/mermaid-js/mermaid" 286 target="_blank" 287 class="link-style"> 288 Mermaid on GitHub 289 </a> 290 </button> 291 <button class="button-style"> 292 <a 293 href="https://github.com/mermaid-js/mermaid-live-editor" 294 target="_blank" 295 class="link-style"> 296 Live Editor on GitHub 297 </a> 298 </button> 299 <button class="button-style"> 300 <a 301 href="https://github.com/mermaid-js/mermaid-cli" 302 target="_blank" 303 class="link-style"> 304 Mermaid CLI 305 </a> 306 </button> 307 </div> 308 </Card> 309 </div> 310 <div id="link-col2"> 311 <Card title="Actions"> 312 <Links /> 313 </Card> 314 </div> 315 </div> 316 </div> 317 </div> 318 <div id="power"> 319 Powered by mermaid 320 <Tag color="green">{mermaidVersion}</Tag> 321 </div> 322</div> 323