Files
mermaid-live-editor/src/routes/edit.svelte
T
2021-05-17 08:57:41 +05:30

145 lines
3.9 KiB
Svelte

<script lang="ts">
import Editor from '$lib/components/editor/editor.svelte';
import Navbar from '$lib/components/navbar.svelte';
import Preset from '$lib/components/preset.svelte';
import Actions from '$lib/components/actions.svelte';
import View from '$lib/components/view.svelte';
import Card from '$lib/components/card/card.svelte';
import History from '$lib/components/history/history.svelte';
import { updateCode, updateConfig, codeStore, base64State } from '$lib/util/state';
import { initHandler, syncDiagram } from '$lib/util/util';
import { errorStore } from '$lib/util/error';
import { onMount } from 'svelte';
import type monaco from 'monaco-editor';
import type { Mermaid } from 'mermaid';
import { version } from 'mermaid/package.json';
import { goto } from '$app/navigation';
const mermaid: Mermaid = (window.mermaid as unknown) as Mermaid;
let selectedMode = 'code';
const languageMap = {
code: 'mermaid',
config: 'json'
};
let text: string = '';
let language: 'mermaid' | 'json' = 'mermaid';
let errorMarkers: monaco.editor.IMarkerData[] = [];
$: language = languageMap[selectedMode];
$: {
if ($codeStore.updateEditor) {
if (selectedMode === 'code') {
text = $codeStore.code;
} else {
text = $codeStore.mermaid;
}
}
}
const tabSelectHandler = (message: CustomEvent<Tab>) => {
$codeStore.updateEditor = true;
selectedMode = message.detail.id;
};
const tabs: Tab[] = [
{
id: 'code',
title: 'Code'
},
{
id: 'config',
title: 'Config'
}
];
const handleCodeUpdate = async (code: string): Promise<void> => {
mermaid.parse(code);
updateCode(code, false);
};
const handleConfigUpdate = (config: string): void => {
JSON.parse(config);
updateConfig(config, false);
};
const updateHandler = async (message: CustomEvent<EditorUpdateEvent>) => {
try {
if (selectedMode === 'code') {
await handleCodeUpdate(message.detail.text);
} else {
handleConfigUpdate(message.detail.text);
}
errorStore.set(undefined);
errorMarkers = [];
} catch (e) {
errorStore.set(e);
if (e.hash) {
const marker: monaco.editor.IMarkerData = {
severity: 8, //Error
startLineNumber: e.hash.loc.first_line,
startColumn: e.hash.loc.first_column,
endLineNumber: e.hash.loc.last_line,
endColumn: e.hash.loc.last_column + 1,
message: e.str
};
errorMarkers.push(marker);
// Clear all previous errors before this error.
errorMarkers = errorMarkers.filter(
(m) => m.startLineNumber >= marker.startLineNumber && m.startColumn >= marker.startColumn
);
}
console.error(e);
}
};
const viewDiagram = async () => {
await goto(`/view#${$base64State}`, { replaceState: true });
};
onMount(initHandler);
</script>
<svelte:head>
<title>Edit</title>
</svelte:head>
<div class="h-full flex flex-col overflow-hidden bg-gray-100">
<Navbar />
<div class="flex-1 flex overflow-hidden">
<div class="w-2/5 flex flex-col">
<Card on:select={tabSelectHandler} {tabs} isCloseable={false} title="Mermaid">
<div slot="actions">
{#if !$codeStore.autoSync}
<button
class="bg-indigo-500 hover:bg-indigo-700 rounded px-1 mx-2"
on:click={syncDiagram}>🔄</button>
{/if}
<label for="autoSync">
<input type="checkbox" name="autoSync" bind:checked={$codeStore.autoSync} />
Auto sync
</label>
</div>
<Editor on:update={updateHandler} {language} {text} {errorMarkers} />
</Card>
<div class="flex-1">
<Preset />
<History />
<Actions />
</div>
</div>
<div class="flex-1 flex flex-col overflow-hidden">
<Card title="Diagram" isCloseable={false}>
<button
slot="actions"
class="rounded shadow px-2 bg-indigo-500 hover:bg-indigo-700"
on:click|stopPropagation={() => viewDiagram()}>View</button>
<div class="flex-1 overflow-auto">
<View />
</div>
</Card>
<div class="self-end mx-2 -mt-2">Powered by Mermaid v{version}</div>
</div>
</div>
</div>