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