From 7f22aea3eb0f17d0bfc0284694bf4cb9eaa10b23 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Mon, 17 Oct 2022 12:00:02 +0530 Subject: [PATCH] Async statestore, Update mermaid version --- package.json | 3 +- src/lib/components/editor.svelte | 10 ++-- src/lib/components/view.svelte | 5 +- src/lib/util/env.ts | 6 +++ src/lib/util/mermaid.ts | 32 +++++++++---- src/lib/util/state.ts | 78 +++++++++++++++++++------------- yarn.lock | 8 ++-- 7 files changed, 88 insertions(+), 54 deletions(-) diff --git a/package.json b/package.json index c8e0a151..9516861d 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "license": "MIT", "scripts": { "dev": "vite dev", + "dev:force": "yarn dev --force", "dev:test": "yarn dev", "build": "vite build", "preview": "vite preview", @@ -68,7 +69,7 @@ "analytics-plugin-plausible": "0.0.6", "daisyui": "2.31.0", "js-base64": "3.7.2", - "mermaid": "9.2.0-rc5", + "mermaid": "9.2.0-rc6", "moment": "2.29.4", "monaco-editor": "0.34.0", "monaco-mermaid": "1.0.6", diff --git a/src/lib/components/editor.svelte b/src/lib/components/editor.svelte index e7a971e0..ab8c1093 100644 --- a/src/lib/components/editor.svelte +++ b/src/lib/components/editor.svelte @@ -53,15 +53,15 @@ }; const loadMonaco = async () => { + console.log('Loading Monaco...'); let i = 0; while (i++ < 500) { - try { - // @ts-ignore : This is a hack to handle a svelte-kit error when importing monaco. - Monaco = window.monaco; + // @ts-ignore : This is a hack to handle a svelte-kit error when importing monaco. + Monaco = window.monaco; + if (Monaco !== undefined) { return; - } catch { - await new Promise((r) => setTimeout(r, 100)); } + await new Promise((r) => setTimeout(r, 100)); } alert('Loading Monaco Editor failed. Please try refreshing the page.'); }; diff --git a/src/lib/components/view.svelte b/src/lib/components/view.svelte index 78c6999c..a8063cd8 100644 --- a/src/lib/components/view.svelte +++ b/src/lib/components/view.svelte @@ -101,9 +101,10 @@ error = true; } }; + onMount(() => { - stateStore.subscribe((state) => { - handleStateChange(state); + stateStore.subscribe(async (state) => { + await handleStateChange(state); }); window.addEventListener('resize', () => { if ($stateStore.panZoom && pzoom) { diff --git a/src/lib/util/env.ts b/src/lib/util/env.ts index 128761f2..354ee3aa 100644 --- a/src/lib/util/env.ts +++ b/src/lib/util/env.ts @@ -2,3 +2,9 @@ export const rendererUrl: string = (import.meta.env.MERMAID_RENDERER_URL as string) ?? 'https://mermaid.ink'; export const krokiRendererUrl: string = (import.meta.env.MERMAID_KROKI_RENDERER_URL as string) ?? 'https://kroki.io'; +export const mermaidCDNUrl: string = + (import.meta.env.MERMAID_CDN_URL as string) ?? 'https://unpkg.com/@mermaid-js'; +export const mermaidBaseURL = + (import.meta.env.MERMAID_BASE_URL as string) ?? 'http://localhost:9000'; +export const isDev = import.meta.env.DEV; +export const baseURL = import.meta.env.BASE_URL; diff --git a/src/lib/util/mermaid.ts b/src/lib/util/mermaid.ts index 2bebc10a..7ae795fc 100644 --- a/src/lib/util/mermaid.ts +++ b/src/lib/util/mermaid.ts @@ -1,15 +1,26 @@ import mermaid from 'mermaid'; // We need to export MermaidConfig and all related types from mermaid. import type { MermaidConfig } from 'mermaid/dist/config.type'; +import { mermaidCDNUrl, isDev, mermaidBaseURL } from './env'; -const init = (async () => { - await mermaid.initializeAsync({ - lazyLoadedDiagrams: [ - 'https://unpkg.com/@mermaid-js/mermaid-mindmap@9.2.0-rc2/dist/mermaid-mindmap-detector.esm.mjs' - ], - loadExternalDiagramsAtStartup: true - }); -})(); +const getDiagramURL = (name: string, version: string): string => { + // if (isDev) { + // // TODO: Check and fallback to CDN if mermaidBaseURL isn't up. + // return `${mermaidBaseURL}/${name}-detector.esm.mjs`; + // } + return `${mermaidCDNUrl}/${name}@${version}/dist/${name}-detector.esm.mjs`; +}; + +console.log(mermaid); +const initialize = mermaid.initializeAsync({ + logLevel: 0, + lazyLoadedDiagrams: [getDiagramURL('mermaid-mindmap', '9.2.0-rc3')], + loadExternalDiagramsAtStartup: true +}); + +export const init = async () => { + await initialize; +}; export const render = async ( config: MermaidConfig, @@ -17,7 +28,7 @@ export const render = async ( id: string, callback: Parameters[2] ): Promise => { - await init; + await init(); // Should be able to call this multiple times without any issues. // await mermaid.initialize({ // ...config, @@ -26,10 +37,11 @@ export const render = async ( // 'https://unpkg.com/@mermaid-js/mermaid-mindmap@9.2.0-rc2/dist/mermaid-mindmap-detector.esm.mjs' // ] // }); + console.log('Rendering', code); await mermaid.mermaidAPI.renderAsync(id, code, callback); }; export const parse = async (code: string): Promise => { - await init; + await init(); return mermaid.parseAsync(code); }; diff --git a/src/lib/util/state.ts b/src/lib/util/state.ts index b66210a0..0306b9a5 100644 --- a/src/lib/util/state.ts +++ b/src/lib/util/state.ts @@ -3,11 +3,13 @@ import { persist, localStorage } from './persist'; import { saveStatistics, countLines } from './stats'; import { serializeState, deserializeState } from './serde'; import { cmdKey } from './util'; -import { parse } from './mermaid'; +import { parse, init } from './mermaid'; import type { Readable } from 'svelte/store'; import type { MarkerData, State, ValidatedState } from '$lib/types'; +void init(); + export const defaultState: State = { code: `graph TD A[Christmas] -->|Get money| B(Go shopping) @@ -42,41 +44,53 @@ const urlParseFailedState = `graph TD export const inputStateStore = persist(writable(defaultState), localStorage(), 'codeStore'); // All internal reads should be done via stateStore, but it should not be persisted/shared externally. -export const stateStore: Readable = derived([inputStateStore], ([state]) => { - const processed: ValidatedState = { - ...state, +export const stateStore: Readable = derived( + [inputStateStore], + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + async ([state], set) => { + const processed: ValidatedState = { + ...state, + serialized: '', + errorMarkers: [], + error: undefined, + editorMode: state.editorMode ?? 'code' + }; + + // No changes should be done to fields part of `state`. + try { + processed.serialized = serializeState(state); + await parse(state.code); + JSON.parse(state.mermaid); + } catch (e) { + processed.error = e; + console.error(e); + if (e.hash) { + try { + const marker: MarkerData = { + 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 as number) + 1, + message: e.str + }; + processed.errorMarkers = [marker]; + } catch (err) { + console.error('Error without line helper', err); + } + } + } + set(processed); + }, + { + ...get(inputStateStore), serialized: '', errorMarkers: [], error: undefined, - editorMode: state.editorMode ?? 'code' - }; - - // No changes should be done to fields part of `state`. - try { - processed.serialized = serializeState(state); - parse(state.code); - JSON.parse(state.mermaid); - } catch (e) { - processed.error = e; - console.error(e); - if (e.hash) { - try { - const marker: MarkerData = { - 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 as number) + 1, - message: e.str - }; - processed.errorMarkers = [marker]; - } catch (err) { - console.error('Error without line helper', err); - } - } + editorMode: get(inputStateStore).editorMode ?? 'code' } - return processed; -}); +); export const loadState = (data: string): void => { let state: State; diff --git a/yarn.lock b/yarn.lock index dc6becb6..304aba00 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3665,10 +3665,10 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -mermaid@9.2.0-rc5: - version "9.2.0-rc5" - resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-9.2.0-rc5.tgz#647c0c0118974c202d93182fdbed27bb01836df1" - integrity sha512-xRKiwHtVe8br4LLuq4X3m3ITOd9CicGfj8YPSWio1u/LJsQHOiGNuBXfp0DWk0StqrlhAJcTmggXp6q/fs9qCA== +mermaid@9.2.0-rc6: + version "9.2.0-rc6" + resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-9.2.0-rc6.tgz#8c8ab4403c5bb9eca73cb8f1aba6fbd00fd8ede9" + integrity sha512-zrbaufHxlWs/i81BZePSh3PtQ/FpS3koY3cX9MS2bclchLqXrzO6wJ5S31Tl95j+7fMzV02HFu3sexSRfJOkhQ== dependencies: "@braintree/sanitize-url" "^6.0.0" d3 "^7.0.0"