Handling of config errors

This commit is contained in:
Knut Sveidqvist
2019-11-17 06:38:04 -08:00
parent dcbd071a51
commit 1251c64a91
14 changed files with 341 additions and 76 deletions
+2
View File
@@ -19,6 +19,8 @@
},
"dependencies": {
"js-base64": "^2.5.1",
"json-lint": "^0.1.0",
"jsonlint": "^1.6.3",
"mermaid": "^8.4.2",
"monaco-editor": "0.18.1",
"svelte-routing": "^1.4.0",
+7 -3
View File
@@ -7,7 +7,7 @@
<title>Svelte app</title>
<link rel='icon' type='image/png' href='favicon.png'>
<link rel='stylesheet' href='global.css'>
<link rel='stylesheet' href='styles.css'>
<link rel='stylesheet' href='bundle.css'>
<style>
.myInlineDecoration {
@@ -18,8 +18,12 @@
background: #ffcccc;
}
</style>
</head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<title>Online FlowChart &amp; Diagrams Editor - Mermaid Live Editor</title>
<meta name="og:image" content="https://mermaid-js.github.io/images/header.png">
<link rel="canonical" href="https://mermaid-js.github.io/mermaid-live-editor/">
<meta name="description" content="Simplify documentation and avoid heavy tools. Open source Visio Alternative. Commonly used for explaining your code! Mermaid is a simple markdown-like script language for generating charts from text via javascript.">
</head>
<body>
<script src='bundle.js'></script>
</body>
+30
View File
@@ -0,0 +1,30 @@
html {
padding: 0;
width: 100%;
height: 100%;
}
body {
padding: 32px;
font-family: 'trebuchet ms', verdana, arial;
position: relative;
width: 100%;
height: 100%;
box-sizing: border-box;
margin: 0;
}
.mermaid {
/* font-family: 'trebuchet ms', verdana, arial; */
}
.marketing-links {
font-size: 16px;
}
.ant-card {
margin-bottom: 16px;
}
i {
font-size: 11px;
}
+1 -3
View File
@@ -25,6 +25,4 @@
<style>
</style>
<body>
<Router {routes}/>
</body>
<Router {routes}/>
+3 -1
View File
@@ -11,8 +11,10 @@ export const fromUrl = data => {
let stateStr = Base64.decode(data)
state = JSON.parse(stateStr);
console.log('state from url', state)
if (state.code === undefined) { // not valid json
state = { code: str, mermaid: { theme: themeFromUrl } }
// state = { code: '', mermaid: { theme: themeFromUrl } }
}
code = state.code;
} catch (e) {
+31
View File
@@ -0,0 +1,31 @@
<script>
export let title = '';
export let noPadding = false;
let contentClass = 'padding';
if (noPadding) {
contentClass = '';
}
</script>
<style>
#card {
border: 1px solid lightgray;
margin-bottom: 16px;
}
#title {
border-bottom: 1px solid lightgray;
}
#content {
padding-top: 16px;
}
.padding {
padding: 16px;
}
</style>
<div id="card">
<div id="title" class="padding">{title}</div>
<div id="content" class="{contentClass}">
<slot></slot>
</div>
</div>
+110
View File
@@ -0,0 +1,110 @@
<script>
import { codeStore, updateCodeStore } from '../code-store.js';
import { configStore } from '../config-store.js';
import { onMount } from 'svelte';
import {push, pop, replace} from 'svelte-spa-router'
import { Base64 } from 'js-base64'
import mermaid from 'mermaid';
import Error from './Error.svelte';
import { initEditor } from './editor-utils';
import 'monaco-editor/esm/vs/editor/browser/controller/coreCommands.js';
import 'monaco-editor/esm/vs/editor/contrib/find/findController.js';
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js';
export let data;
export let conf = '';
export let code = '';
export let error = false;
let edit;
let decorations = [];
const decArr = [];
let oldConf = { theme: 'default' };
const handleConfUpdate = conf => {
try {
JSON.parse(conf);
console.log(code);
let newState = { code, mermaid: JSON.parse(conf) };
oldConf = newState.mermaid;
updateCodeStore(newState);
configStore.set(undefined);
const model = edit.getModel();
// model.setValue(conf);
// model.dispose();
} catch(e) {
console.log('Error in parsed', e);
configStore.set(e);
const str = JSON.stringify({ code, mermaid: oldConf });
push('/edit/' + Base64.encode(str))
}
};
const unsubscribe = codeStore.subscribe( state => {
if(!conf && state) {
conf = JSON.stringify(state.mermaid, null, 2);
}
if(state) {
code = state.code;
}
if(!edit && conf) {
edit = monaco.editor.create(document.getElementById('editor-conf'), {
value: [
conf,
].join('\n'),
theme: 'myCoolTheme',
language: 'JSON'
});
let decorations = [];
edit.onDidChangeModelContent(function (e) {
const conf = edit.getValue();
handleConfUpdate(conf);
});
handleConfUpdate(conf);
}
});
initEditor(monaco);
const unsubscribeError = configStore.subscribe( _error => {
// console.log('Error ideintified' + _error.toString());
if(_error) {
error = _error.toString();
} else {
error = false;
}
});
onMount(async () => {
console.log('Mounting config');
self.MonacoEnvironment = {
getWorkerUrl: function (moduleId, label) {
return './editor.worker.bundle.js';
}
}
});
export let name;
export let params = {};
export let errorText = ''
</script>
<style>
#editor-container {}
#editor-conf {
width: 100%;
height: 200px;
max-height: 300px;
flex: 1;
}
</style>
<div id="editor-container">
<div id="editor-conf"> </div>
{#if error}
<Error errorText={error}/>
{/if}
</div>
+27 -34
View File
@@ -13,43 +13,34 @@ import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js';
export let data;
export let code = '';
export let conf = { theme: 'default' };
let edit;
export let error = false;
let decorations = [];
const decArr = [];
const handleCodeUpdate = code => {
try {
mermaid.parse(code);
let newState = { code, mermaid: { theme: 'default' } };
let newState = { code, mermaid: conf };
updateCodeStore(newState);
decArr.forEach(decor => {
edit.deltaDecorations(decor, []);
});
// decorations = edit.deltaDecorations(decorations, [{ range: new monaco.Range(1,1,1,1), options : { } }]);
errorStore.set(undefined);
const model = edit.getModel();
// model.setValue(code);
// model.dispose();
} catch(e) {
console.log('Error in parsed', e);
if(e) {
errorStore.set(e);
const str = JSON.stringify({ code: code, mermaid: { theme: 'default' } });
console.log('Error in parsed', e.hash);
const str = JSON.stringify({ code: code, mermaid: conf });
push('/edit/' + Base64.encode(str))
const l = e.hash.line;
decArr.push(edit.deltaDecorations([], [
{ range: new monaco.Range(e.hash.loc.first_line,e.hash.loc.last_line,e.hash.loc.first_column,e.hash.loc.last_column), options: { inlineClassName: 'myInlineDecoration' }}]
));
// const model = edit.getModel();
// monaco.editor.setModelMarkers(model, 'test', {
// startLineineNumber: e.hash.loc.first_line,
// endLineNumumber: e.hash.loc.last_line,
// startColumn: e.hash.loc.first_column,
// endColumn: e.hash.loc.last_column,
// message: 'Syntax error',
// code: 'SXE',
// severity: 8
// });
}
}
};
@@ -57,6 +48,9 @@ const unsubscribe = codeStore.subscribe( state => {
if(!code && state) {
code = state.code;
}
if(state) {
conf = state.mermaid;
}
if(!edit && code) {
edit = monaco.editor.create(document.getElementById('editor'), {
value: [
@@ -75,6 +69,14 @@ const unsubscribe = codeStore.subscribe( state => {
}
});
const unsubscribeError = errorStore.subscribe( _error => {
if(_error) {
error = true;
} else {
error = false;
}
});
initEditor(monaco);
onMount(async () => {
@@ -87,31 +89,22 @@ onMount(async () => {
});
export let name;
export let params = {}
export let params = {};
</script>
<style>
#editor-container {
height: 80%;
max-height: 400px;
border: 1px solor darkred;
flex: 1;
}
#editor-container {}
#editor {
height: 80%;
max-height: 400px;
border: 1px solor darkred;
width: 100%;
height: 400px;
max-height: 300px;
flex: 1;
}
/* .myLineDecoration {
background: lightblue;
width: 50px !important;
margin-left: 3px;
} */
</style>
<div id="editor-container">
<div id="editor"> </div>
<Error />
{#if error}
<Error errorText="Syntax Error"/>
{/if}
</div>
+18 -19
View File
@@ -13,27 +13,29 @@ onMount(async () => {
export let expected = '';
export let params = {}
export let errorText = '';
const unsubscribeError = errorStore.subscribe( _error => {
if(typeof _error === 'undefined') {
classes = 'invisible';
error = {};
token='';
expected='';
} else {
classes = 'visible';
error = _error;
console.log('error: ', _error);
token = error.hash.token;
expected = error.hash.expected.join(' ');;
}
});
// const unsubscribeError = errorStore.subscribe( _error => {
// if(typeof _error === 'undefined') {
// classes = 'invisible';
// error = {};
// token='';
// expected='';
// } else {
// classes = 'visible';
// error = _error;
// console.log('error: ', _error);
// token = error.hash.token;
// expected = error.hash.expected.join(' ');;
// }
// });
</script>
<style>
#error {
border: 1px solid darkred;
background: darkred;
color: white;
flex: 1;
padding: 10px;
/* position: absolute; */
@@ -47,8 +49,5 @@ const unsubscribeError = errorStore.subscribe( _error => {
}
</style>
<div id="error" class="{classes}">
<div>Expected: {expected}</div>
<br/>
<div>Got: {token}</div>
<div id="error" class="{classes}">{errorText}
</div>
+15 -4
View File
@@ -1,6 +1,7 @@
<script>
import { codeStore } from '../code-store.js';
import { errorStore } from '../error-store.js';
import { configStore } from '../config-store.js';
import { onMount } from 'svelte';
import mermaid from 'mermaid';
@@ -15,13 +16,15 @@ let insertSvg = function(svgCode, bindFunctions){
};
export let code = '';
export let classes = '';
export let configClasses = '';
export let codeClasses = '';
const unsubscribe = codeStore.subscribe( state => {
try {
if(container && state) {
code = state.code;
container.innerHTML = code;
delete container.dataset.processed
mermaid.initialize(state.mermaid)
mermaid.init(undefined, container)
if(code) mermaid.render('graph-div', code, insertSvg);
}
@@ -32,9 +35,17 @@ let insertSvg = function(svgCode, bindFunctions){
});
const unsubscribeError = errorStore.subscribe( _error => {
if(typeof _error === 'undefined') {
classes = '';
codeClasses = '';
} else {
classes = 'error';
codeClasses = 'error';
console.log('error: ', typeof _error);
}
});
const unsubscribeConfigError = configStore.subscribe( _error => {
if(typeof _error === 'undefined') {
configClasses = '';
} else {
configClasses = 'error';
console.log('error: ', typeof _error);
}
});
@@ -50,6 +61,6 @@ let insertSvg = function(svgCode, bindFunctions){
}
</style>
<div id="view" class="{classes}">
<div id="view" class="{codeClasses} {configClasses}">
<div bind:this={container}></div>
</div>
+3
View File
@@ -0,0 +1,3 @@
import { writable } from 'svelte/store';
export const configStore = writable(undefined);
+1 -1
View File
@@ -1,3 +1,3 @@
import { writable } from 'svelte/store';
export const errorStore = writable(undefined);
export const errorStore = writable({});
+32 -5
View File
@@ -1,7 +1,9 @@
<script>
import { onMount } from 'svelte';
import Editor from '../components/Editor.svelte';
import Config from '../components/Config.svelte';
import View from '../components/View.svelte';
import Card from '../components/Card.svelte';
import { fromUrl } from '../code-store.js';
onMount(async () => {
@@ -20,13 +22,38 @@ onMount(async () => {
</script>
<style>
#editor-container {
#editor-root {
display: flex;
height: 100%;
}
</style>
<div id="editor-container">
<Editor data={params.data}/>
<View />
#col1 {
width: 35%;
}
#col2 {
width: 65%;
padding-left: 32px;
}
#app-title {
border-bottom: 1px solid lightgrey;
padding-bottom: 32px;
margin-bottom: 32px;
font-size: 28px;
font-weight: 400;
margin-top: 0;
}
</style>
<div>
<h1 id="app-title">Mermaid Live Editor</h1>
<div id="editor-root">
<div id="col1">
<Card title="Code" noPadding="true"><Editor data={params.data}/></Card>
<Card title="Mermaid Configuration" ><Config /></Card>
</div>
<div id="col2">
<Card title="Preview"><View /></Card>
<Card title="Actions">bla boac</Card>
</div>
</div>
</div>
+55
View File
@@ -192,6 +192,11 @@
resolved "http://pacman01.inkclub.local:4873/@zeit%2fschemas/-/schemas-2.6.0.tgz#004e8e553b4cd53d538bd38eac7bcbf58a867fe3"
integrity sha512-uUrgZ8AxS+Lio0fZKAipJjAh415JyrOZowliZAzmnJSsf7piVL5w+G0+gFJ0KSu3QRhvui/7zuvpLz03YjXAhg==
JSV@^4.0.x:
version "4.0.2"
resolved "https://registry.yarnpkg.com/JSV/-/JSV-4.0.2.tgz#d077f6825571f82132f9dffaed587b4029feff57"
integrity sha1-0Hf2glVx+CEy+d/67Vh7QCn+/1c=
abbrev@1:
version "1.1.1"
resolved "http://pacman01.inkclub.local:4873/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
@@ -279,6 +284,11 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1:
dependencies:
color-convert "^1.9.0"
ansi-styles@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.0.0.tgz#cb102df1c56f5123eab8b67cd7b98027a0279178"
integrity sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=
anymatch@^2.0.0:
version "2.0.0"
resolved "http://pacman01.inkclub.local:4873/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb"
@@ -684,6 +694,15 @@ chalk@2.4.2, chalk@^2.0.1, chalk@^2.4.2:
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
chalk@~0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.4.0.tgz#5199a3ddcd0c1efe23bc08c1b027b06176e0c64f"
integrity sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=
dependencies:
ansi-styles "~1.0.0"
has-color "~0.1.0"
strip-ansi "~0.1.0"
chokidar@^2.0.2, chokidar@^2.1.8:
version "2.1.8"
resolved "http://pacman01.inkclub.local:4873/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917"
@@ -2036,6 +2055,11 @@ handle-thing@^2.0.0:
resolved "http://pacman01.inkclub.local:4873/handle-thing/-/handle-thing-2.0.0.tgz#0e039695ff50c93fc288557d696f3c1dc6776754"
integrity sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==
has-color@~0.1.0:
version "0.1.7"
resolved "https://registry.yarnpkg.com/has-color/-/has-color-0.1.7.tgz#67144a5260c34fc3cca677d041daf52fe7b78b2f"
integrity sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=
has-flag@^3.0.0:
version "3.0.0"
resolved "http://pacman01.inkclub.local:4873/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
@@ -2548,6 +2572,11 @@ js-base64@^2.5.1:
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.1.tgz#1efa39ef2c5f7980bb1784ade4a8af2de3291121"
integrity sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==
json-lint@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/json-lint/-/json-lint-0.1.0.tgz#45b03fba86c4f30f2c6e70aa73a90d3fe18f9803"
integrity sha1-RbA/uobE8w8sbnCqc6kNP+GPmAM=
json-parse-better-errors@^1.0.2:
version "1.0.2"
resolved "http://pacman01.inkclub.local:4873/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
@@ -2570,6 +2599,14 @@ json5@^1.0.1:
dependencies:
minimist "^1.2.0"
jsonlint@^1.6.3:
version "1.6.3"
resolved "https://registry.yarnpkg.com/jsonlint/-/jsonlint-1.6.3.tgz#cb5e31efc0b78291d0d862fbef05900adf212988"
integrity sha512-jMVTMzP+7gU/IyC6hvKyWpUU8tmTkK5b3BPNuMI9U8Sit+YAWLlZwB6Y6YrdCxfg2kNz05p3XY3Bmm4m26Nv3A==
dependencies:
JSV "^4.0.x"
nomnom "^1.5.x"
killable@^1.0.1:
version "1.0.1"
resolved "http://pacman01.inkclub.local:4873/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892"
@@ -3077,6 +3114,14 @@ node-pre-gyp@^0.12.0:
semver "^5.3.0"
tar "^4"
nomnom@^1.5.x:
version "1.8.1"
resolved "https://registry.yarnpkg.com/nomnom/-/nomnom-1.8.1.tgz#2151f722472ba79e50a76fc125bb8c8f2e4dc2a7"
integrity sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=
dependencies:
chalk "~0.4.0"
underscore "~1.6.0"
nopt@^4.0.1:
version "4.0.1"
resolved "http://pacman01.inkclub.local:4873/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d"
@@ -4276,6 +4321,11 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0:
dependencies:
ansi-regex "^4.1.0"
strip-ansi@~0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.1.1.tgz#39e8a98d044d150660abe4a6808acf70bb7bc991"
integrity sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=
strip-css-comments@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/strip-css-comments/-/strip-css-comments-3.0.0.tgz#7a5625eff8a2b226cf8947a11254da96e13dae89"
@@ -4495,6 +4545,11 @@ uglify-js@^3.5.1:
commander "~2.20.3"
source-map "~0.6.1"
underscore@~1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.6.0.tgz#8b38b10cacdef63337b8b24e4ff86d45aea529a8"
integrity sha1-izixDKze9jM3uLJOT/htRa6lKag=
union-value@^1.0.0:
version "1.0.1"
resolved "http://pacman01.inkclub.local:4873/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847"