Merge branch 'master-holder'
* master-holder: (72 commits) Release 1.22.10 Clipboard icon Release 1.22.10 Space for tabs Release 1.22.10 Nojekyll Release 1.22.10 Fix path Release 1.22.10 Disable jekyll Release 1.22.10 Fix base path Release 1.22.10 Hide editor on mobile Remove netlify Remove doce Try netlify Release 1.22.10 Rename branch Deploy ...
This commit is contained in:
@@ -0,0 +1,20 @@
|
|||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'],
|
||||||
|
plugins: ['svelte3', '@typescript-eslint'],
|
||||||
|
ignorePatterns: ['*.cjs'],
|
||||||
|
overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }],
|
||||||
|
settings: {
|
||||||
|
'svelte3/typescript': () => require('typescript')
|
||||||
|
},
|
||||||
|
parserOptions: {
|
||||||
|
sourceType: 'module',
|
||||||
|
ecmaVersion: 2019
|
||||||
|
},
|
||||||
|
env: {
|
||||||
|
browser: true,
|
||||||
|
es2017: true,
|
||||||
|
node: true
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -19,7 +19,8 @@ jobs:
|
|||||||
npm i -g yarn
|
npm i -g yarn
|
||||||
yarn install
|
yarn install
|
||||||
yarn version --patch --no-git-tag-version
|
yarn version --patch --no-git-tag-version
|
||||||
yarn release
|
export CI=true
|
||||||
|
yarn build
|
||||||
git config user.name github-actions
|
git config user.name github-actions
|
||||||
git config user.email github-actions@github.com
|
git config user.email github-actions@github.com
|
||||||
git add .
|
git add .
|
||||||
|
|||||||
+4
-1
@@ -4,4 +4,7 @@ coverage/
|
|||||||
build/
|
build/
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
.npmrc
|
.npmrc
|
||||||
*node_modules*
|
.DS_Store
|
||||||
|
/.svelte-kit
|
||||||
|
/build
|
||||||
|
/functions
|
||||||
|
|||||||
+5
-1
@@ -1 +1,5 @@
|
|||||||
dist/
|
docs/**
|
||||||
|
.svelte-kit/**
|
||||||
|
static/**
|
||||||
|
build/**
|
||||||
|
node_modules/**
|
||||||
|
|||||||
+6
-3
@@ -1,5 +1,8 @@
|
|||||||
{
|
{
|
||||||
"singleQuote": true,
|
"singleQuote": true,
|
||||||
"svelteSortOrder": "scripts-styles-markup",
|
"svelteSortOrder": "scripts-styles-markup",
|
||||||
"svelteBracketNewLine": false
|
"svelteBracketNewLine": false,
|
||||||
|
"useTabs": true,
|
||||||
|
"trailingComma": "none",
|
||||||
|
"printWidth": 100
|
||||||
}
|
}
|
||||||
@@ -46,8 +46,7 @@ registry=https://registry.npmjs.com/
|
|||||||
## Development
|
## Development
|
||||||
|
|
||||||
```
|
```
|
||||||
yarn dev
|
yarn dev -- --open
|
||||||
open http://localhost:8080
|
|
||||||
```
|
```
|
||||||
|
|
||||||
This app is created with Svelte + svelte-spa-router.
|
This app is created with Svelte + svelte-spa-router.
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
|||||||
|
#menu-toggle.svelte-1q1rl80:checked+#menu.svelte-1q1rl80{display:block}.nav-btn.svelte-1q1rl80.svelte-1q1rl80{border-color:transparent}.nav-btn.svelte-1q1rl80.svelte-1q1rl80:hover{--tw-border-opacity:1;border-color:rgba(255,255,255,var(--tw-border-opacity))}.nav-btn.svelte-1q1rl80.svelte-1q1rl80{border-bottom-width:2px;display:block;padding:.75rem 0}@media(min-width:1024px){.nav-btn.svelte-1q1rl80.svelte-1q1rl80{padding:.5rem}}.isOpen.svelte-1j9xzww{transform:rotate(-90deg);transition-duration:.5s}.btn.svelte-1ygdo6x{background-color:rgba(129,140,248,var(--tw-bg-opacity))}.btn.svelte-1ygdo6x,.btn.svelte-1ygdo6x:hover{--tw-bg-opacity:1}.btn.svelte-1ygdo6x:hover{background-color:rgba(99,102,241,var(--tw-bg-opacity))}.btn.svelte-1ygdo6x{--tw-shadow:0 1px 3px 0 rgba(0,0,0,0.1),0 1px 2px 0 rgba(0,0,0,0.06);--tw-text-opacity:1;border-radius:.25rem;box-shadow:var(--tw-ring-offset-shadow,0 0 transparent),var(--tw-ring-shadow,0 0 transparent),var(--tw-shadow);color:rgba(255,255,255,var(--tw-text-opacity));flex:1 1 auto;padding:.5rem}.btn.svelte-15pcoti{background-color:rgba(99,102,241,var(--tw-bg-opacity))}.btn.svelte-15pcoti,.btn.svelte-15pcoti:hover{--tw-bg-opacity:1}.btn.svelte-15pcoti:hover{background-color:rgba(67,56,202,var(--tw-bg-opacity))}.btn.svelte-15pcoti{--tw-shadow:0 1px 3px 0 rgba(0,0,0,0.1),0 1px 2px 0 rgba(0,0,0,0.06);border-radius:.25rem;box-shadow:var(--tw-ring-offset-shadow,0 0 transparent),var(--tw-ring-shadow,0 0 transparent),var(--tw-shadow);padding-left:1rem;padding-right:1rem}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
#svelte-announcer.svelte-1pdgbjn{clip:rect(0 0 0 0);-webkit-clip-path:inset(50%);clip-path:inset(50%);height:1px;left:0;overflow:hidden;position:absolute;top:0;white-space:nowrap;width:1px}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
#view.svelte-7vvt6c{border:1px #8b0000;flex:1}.error.svelte-7vvt6c,.outOfSync.svelte-7vvt6c{opacity:.5}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import{r as o}from"./singletons-bb9012b7.js";const n=async function(n,s){return o.goto(n,s,[])};export{n as g};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
let s="",a="/.";function e(e){({base:s,assets:a}=e)}export{s as b,e as s};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
let t;function a(a){t=a}export{a as i,t as r};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
var e=Object.defineProperty,a=Object.prototype.hasOwnProperty,t=Object.getOwnPropertySymbols,n=Object.prototype.propertyIsEnumerable,o=(a,t,n)=>t in a?e(a,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):a[t]=n,r=(e,r)=>{for(var s in r||(r={}))a.call(r,s)&&o(e,s,r[s]);if(t)for(var s of t(r))n.call(r,s)&&o(e,s,r[s]);return e};import{a2 as s,a3 as i,C as c,a4 as l,a0 as d,a6 as u,a9 as p,S as f,i as h,s as m,e as y,c as g,a as v,d as b,b as w,O,f as S,F as E,G as x,a7 as D,z as C,a8 as T,J as j}from"./vendor-a9bf48e1.js";const J=s(c({code:"graph TD\n A[Christmas] --\x3e|Get money| B(Go shopping)\n B --\x3e C{Let me think}\n C --\x3e|One| D[Laptop]\n C --\x3e|Two| E[iPhone]\n C --\x3e|Three| F[fa:fa-car Car]\n ",mermaid:JSON.stringify({theme:"default"},null,2),updateEditor:!1,autoSync:!0,updateDiagram:!0}),i(),"codeStore"),N=l([J],(([e],a)=>{a(d(JSON.stringify(e),!0))})),P=e=>{J.update((a=>r(r({},a),e)))};let I=!1;const L=(e,a,t=!1)=>{if((e.match(/\n/g)||"").length+1>50&&!I&&u(J).autoSync){const e=confirm("Long diagram deteced. Turn off Auto Sync? Click the sync logo to manually sync.");I=!0,e&&P({autoSync:!1})}J.update((n=>r(r({},n),{code:e,updateEditor:a,updateDiagram:t})))},G=(e,a)=>{J.update((t=>r(r({},t),{mermaid:e,updateEditor:a})))},V=()=>JSON.stringify(u(J)),k=c(void 0);function z(e){let a,t;return{c(){a=y("div"),t=y("div"),this.h()},l(e){a=g(e,"DIV",{id:!0,class:!0});var n=v(a);t=g(n,"DIV",{id:!0,class:!0}),v(t).forEach(b),n.forEach(b),this.h()},h(){w(t,"id","container"),w(t,"class","flex-1 overflow-auto"),w(a,"id","view"),w(a,"class","p-2 svelte-7vvt6c"),O(a,"error",e[1]),O(a,"outOfSync",e[2])},m(n,o){S(n,a,o),E(a,t),e[3](t)},p(e,[t]){2&t&&O(a,"error",e[1]),4&t&&O(a,"outOfSync",e[2])},i:x,o:x,d(t){t&&b(a),e[3](null)}}}function A(e,a,t){let n;D(e,J,(e=>t(6,n=e)));var o=this&&this.__awaiter||function(e,a,t,n){return new(t||(t=Promise))((function(o,r){function s(e){try{c(n.next(e))}catch(a){r(a)}}function i(e){try{c(n.throw(e))}catch(a){r(a)}}function c(e){var a;e.done?o(e.value):(a=e.value,a instanceof t?a:new t((function(e){e(a)}))).then(s,i)}c((n=n.apply(e,a||[])).next())}))};const r=window.mermaid;let s,i="",c=!1,l=!1,d=!0;C((()=>o(void 0,void 0,void 0,(function*(){J.subscribe((e=>{try{if(s&&e&&(e.updateDiagram||e.autoSync)){e.autoSync||T(J,n.updateDiagram=!1,n),t(2,l=!1),d=!0,i=e.code;const a=s.parentElement.parentElement.parentElement.scrollTop;t(0,s.innerHTML=i,s),delete s.dataset.processed,r.initialize(Object.assign({},JSON.parse(e.mermaid))),r.init(s),r.render("graph-div",i,u),t(0,s.parentElement.parentElement.parentElement.scrollTop=a,s)}else d?d=!1:t(2,l=!0)}catch(a){console.log("view fail",a),t(1,c=!0)}})),k.subscribe((e=>{void 0===e?t(1,c=!1):(t(1,c=!0),console.log("Error: ",e))}))}))));const u=(e,a)=>{};return[s,c,l,function(e){j[e?"unshift":"push"]((()=>{s=e,t(0,s)}))}]}class B extends f{constructor(e){super(),h(this,e,A,z,m,{})}}const F=()=>{(e=>{let a;try{const t=p(e);console.log(`Tring to load state: ${t}`),a=JSON.parse(t)}catch(t){e&&console.error("Init error",t),a=u(J),console.log(a)}P(r(r({},a),{updateEditor:!0}))})(window.location.hash.slice(1))},_=()=>{P({updateDiagram:!0})},H=()=>{F(),_(),N.subscribe((e=>{window.location.hash=e}))};export{B as V,G as a,N as b,J as c,k as e,V as g,H as i,_ as s,L as u};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
var e=Object.defineProperty,a=Object.prototype.hasOwnProperty,t=Object.getOwnPropertySymbols,n=Object.prototype.propertyIsEnumerable,o=(a,t,n)=>t in a?e(a,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):a[t]=n,r=(e,r)=>{for(var s in r||(r={}))a.call(r,s)&&o(e,s,r[s]);if(t)for(var s of t(r))n.call(r,s)&&o(e,s,r[s]);return e};import{a2 as s,a3 as i,C as c,a4 as l,a0 as d,a6 as u,a9 as p,S as f,i as h,s as m,e as y,c as v,a as g,d as b,b as w,O,f as S,F as E,G as x,a7 as D,z as C,a8 as T,J as j}from"./vendor-a9bf48e1.js";const J=s(c({code:"graph TD\n A[Christmas] --\x3e|Get money| B(Go shopping)\n B --\x3e C{Let me think}\n C --\x3e|One| D[Laptop]\n C --\x3e|Two| E[iPhone]\n C --\x3e|Three| F[fa:fa-car Car]\n ",mermaid:JSON.stringify({theme:"default"}),updateEditor:!1,autoSync:!0,updateDiagram:!0}),i(),"codeStore"),N=l([J],(([e],a)=>{a(d(JSON.stringify(e),!0))})),P=e=>{J.update((a=>r(r({},a),e)))};let I=!1;const L=(e,a,t=!1)=>{if((e.match(/\n/g)||"").length+1>50&&!I&&u(J).autoSync){const e=confirm("Long diagram deteced. Turn off Auto Sync? Click the sync logo to manually sync.");I=!0,e&&P({autoSync:!1})}J.update((n=>r(r({},n),{code:e,updateEditor:a,updateDiagram:t})))},G=(e,a)=>{J.update((t=>r(r({},t),{mermaid:e,updateEditor:a})))},V=()=>JSON.stringify(u(J)),k=c(void 0);function z(e){let a,t;return{c(){a=y("div"),t=y("div"),this.h()},l(e){a=v(e,"DIV",{id:!0,class:!0});var n=g(a);t=v(n,"DIV",{id:!0,class:!0}),g(t).forEach(b),n.forEach(b),this.h()},h(){w(t,"id","container"),w(t,"class","flex-1 overflow-auto"),w(a,"id","view"),w(a,"class","p-2 svelte-7vvt6c"),O(a,"error",e[1]),O(a,"outOfSync",e[2])},m(n,o){S(n,a,o),E(a,t),e[3](t)},p(e,[t]){2&t&&O(a,"error",e[1]),4&t&&O(a,"outOfSync",e[2])},i:x,o:x,d(t){t&&b(a),e[3](null)}}}function A(e,a,t){let n;D(e,J,(e=>t(6,n=e)));var o=this&&this.__awaiter||function(e,a,t,n){return new(t||(t=Promise))((function(o,r){function s(e){try{c(n.next(e))}catch(a){r(a)}}function i(e){try{c(n.throw(e))}catch(a){r(a)}}function c(e){var a;e.done?o(e.value):(a=e.value,a instanceof t?a:new t((function(e){e(a)}))).then(s,i)}c((n=n.apply(e,a||[])).next())}))};const r=window.mermaid;let s,i="",c=!1,l=!1,d=!0;C((()=>o(void 0,void 0,void 0,(function*(){J.subscribe((e=>{try{if(s&&e&&(e.updateDiagram||e.autoSync)){e.autoSync||T(J,n.updateDiagram=!1,n),t(2,l=!1),d=!0,i=e.code;const a=s.parentElement.parentElement.parentElement.scrollTop;t(0,s.innerHTML=i,s),delete s.dataset.processed,r.initialize(Object.assign({},JSON.parse(e.mermaid))),r.init(s),r.render("graph-div",i,u),t(0,s.parentElement.parentElement.parentElement.scrollTop=a,s)}else d?d=!1:t(2,l=!0)}catch(a){console.log("view fail",a),t(1,c=!0)}})),k.subscribe((e=>{void 0===e?t(1,c=!1):(t(1,c=!0),console.log("Error: ",e))}))}))));const u=(e,a)=>{};return[s,c,l,function(e){j[e?"unshift":"push"]((()=>{s=e,t(0,s)}))}]}class B extends f{constructor(e){super(),h(this,e,A,z,m,{})}}const F=()=>{(e=>{let a;try{const t=p(e);a=JSON.parse(t)}catch(t){console.error("Init error",t),a=u(J)}P(r(r({},a),{updateEditor:!0}))})(window.location.hash.slice(1))},_=()=>{P({updateDiagram:!0})},H=()=>{F(),_(),N.subscribe((e=>{window.location.hash=e}))};export{B as V,G as a,N as b,J as c,k as e,V as g,H as i,_ as s,L as u};
|
||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
|||||||
|
import{S as s,i as r,s as a,e as t,t as e,c as o,a as n,g as c,d as u,f as p,F as f,h as l,k as i,l as d,n as m,G as h}from"./chunks/vendor-a9bf48e1.js";function k(s){let r,a,i=s[1].stack+"";return{c(){r=t("pre"),a=e(i)},l(s){r=o(s,"PRE",{});var t=n(r);a=c(t,i),t.forEach(u)},m(s,t){p(s,r,t),f(r,a)},p(s,r){2&r&&i!==(i=s[1].stack+"")&&l(a,i)},d(s){s&&u(r)}}}function v(s){let r,a,v,E,g,x,P,$=s[1].message+"",b=s[1].stack&&k(s);return{c(){r=t("h1"),a=e(s[0]),v=i(),E=t("p"),g=e($),x=i(),b&&b.c(),P=d()},l(t){r=o(t,"H1",{});var e=n(r);a=c(e,s[0]),e.forEach(u),v=m(t),E=o(t,"P",{});var p=n(E);g=c(p,$),p.forEach(u),x=m(t),b&&b.l(t),P=d()},m(s,t){p(s,r,t),f(r,a),p(s,v,t),p(s,E,t),f(E,g),p(s,x,t),b&&b.m(s,t),p(s,P,t)},p(s,[r]){1&r&&l(a,s[0]),2&r&&$!==($=s[1].message+"")&&l(g,$),s[1].stack?b?b.p(s,r):(b=k(s),b.c(),b.m(P.parentNode,P)):b&&(b.d(1),b=null)},i:h,o:h,d(s){s&&u(r),s&&u(v),s&&u(E),s&&u(x),b&&b.d(s),s&&u(P)}}}function E({error:s,status:r}){return{props:{error:s,status:r}}}function g(s,r,a){let{status:t}=r,{error:e}=r;return s.$$set=s=>{"status"in s&&a(0,t=s.status),"error"in s&&a(1,e=s.error)},[t,e]}export default class extends s{constructor(s){super(),r(this,s,g,v,a,{status:0,error:1})}}export{E as load};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import{S as s,i as a,s as e,D as t,e as l,c as n,a as c,d as o,b as r,f as u,E as i,v as $,r as h}from"../chunks/vendor-a9bf48e1.js";function f(s){let a,e;const f=s[1].default,p=t(f,s,s[0],null);return{c(){a=l("main"),p&&p.c(),this.h()},l(s){a=n(s,"MAIN",{class:!0});var e=c(a);p&&p.l(e),e.forEach(o),this.h()},h(){r(a,"class","h-screen")},m(s,t){u(s,a,t),p&&p.m(a,null),e=!0},p(s,[a]){p&&p.p&&(!e||1&a)&&i(p,f,s,s[0],a,null,null)},i(s){e||($(p,s),e=!0)},o(s){h(p,s),e=!1},d(s){s&&o(a),p&&p.d(s)}}}function p(s,a,e){let{$$slots:t={},$$scope:l}=a;return s.$$set=s=>{"$$scope"in s&&e(0,l=s.$$scope)},[l,t]}export default class extends s{constructor(s){super(),a(this,s,p,f,e,{})}}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import{S as s,i as a,s as e,D as t,e as l,c as n,a as c,d as o,b as r,f as u,E as i,v as $,r as h}from"../chunks/vendor-a9bf48e1.js";function f(s){let a,e;const f=s[1].default,p=t(f,s,s[0],null);return{c(){a=l("main"),p&&p.c(),this.h()},l(s){a=n(s,"MAIN",{class:!0});var e=c(a);p&&p.l(e),e.forEach(o),this.h()},h(){r(a,"class","h-screen")},m(s,t){u(s,a,t),p&&p.m(a,null),e=!0},p(s,[a]){p&&p.p&&(!e||1&a)&&i(p,f,s,s[0],a,null,null)},i(s){e||($(p,s),e=!0)},o(s){h(p,s),e=!1},d(s){s&&o(a),p&&p.d(s)}}}function p(s,a,e){let{$$slots:t={},$$scope:l}=a;return s.$$set=s=>{"$$scope"in s&&e(0,l=s.$$scope)},[l,t]}export default class extends s{constructor(s){super(),a(this,s,p,f,e,{})}}
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
|||||||
|
import{S as t,i as n,s as e,H as i,d as o,G as s,z as a}from"../chunks/vendor-a9bf48e1.js";import{g as c}from"../chunks/navigation-20968cc5.js";import{b as r}from"../chunks/paths-45dac81d.js";import"../chunks/singletons-bb9012b7.js";function u(t){return{c(){this.h()},l(t){i('[data-svelte="svelte-wtz6kg"]',document.head).forEach(o),this.h()},h(){document.title="Mermaid Live Editor"},m:s,p:s,i:s,o:s,d:s}}function h(t){var n=this&&this.__awaiter||function(t,n,e,i){return new(e||(e=Promise))((function(o,s){function a(t){try{r(i.next(t))}catch(n){s(n)}}function c(t){try{r(i.throw(t))}catch(n){s(n)}}function r(t){var n;t.done?o(t.value):(n=t.value,n instanceof e?n:new e((function(t){t(n)}))).then(a,c)}r((i=i.apply(t,n||[])).next())}))};return a((()=>n(void 0,void 0,void 0,(function*(){const t=window.location.hash.split("/");let n="edit";t.length>2&&(n=`${t[1]}#${t[2]}`),yield c(`${r}/${n}`,{replaceState:!0})})))),[]}export default class extends t{constructor(t){super(),n(this,t,h,u,e,{})}}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import{S as t,i as n,s as e,H as i,d as o,G as s,z as a}from"../chunks/vendor-a9bf48e1.js";import{g as c}from"../chunks/navigation-20968cc5.js";import"../chunks/singletons-bb9012b7.js";function r(t){return{c(){this.h()},l(t){i('[data-svelte="svelte-wtz6kg"]',document.head).forEach(o),this.h()},h(){document.title="Mermaid Live Editor"},m:s,p:s,i:s,o:s,d:s}}function u(t){var n=this&&this.__awaiter||function(t,n,e,i){return new(e||(e=Promise))((function(o,s){function a(t){try{r(i.next(t))}catch(n){s(n)}}function c(t){try{r(i.throw(t))}catch(n){s(n)}}function r(t){var n;t.done?o(t.value):(n=t.value,n instanceof e?n:new e((function(t){t(n)}))).then(a,c)}r((i=i.apply(t,n||[])).next())}))};return a((()=>n(void 0,void 0,void 0,(function*(){const t=window.location.hash.split("/");let n="/edit";t.length>2&&(n=`/${t[1]}#${t[2]}`),yield c(n,{replaceState:!0})})))),[]}export default class extends t{constructor(t){super(),n(this,t,u,r,e,{})}}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import{S as s,i as a,s as r,j as t,m as n,o as e,G as o,v as f,r as m,w as u,z as i}from"../chunks/vendor-a9bf48e1.js";import{V as c,i as $}from"../chunks/util-bfd89a15.js";function d(s){let a,r;return a=new c({}),{c(){t(a.$$.fragment)},l(s){n(a.$$.fragment,s)},m(s,t){e(a,s,t),r=!0},p:o,i(s){r||(f(a.$$.fragment,s),r=!0)},o(s){m(a.$$.fragment,s),r=!1},d(s){u(a,s)}}}function l(s){return i($),[]}export default class extends s{constructor(s){super(),a(this,s,l,d,r,{})}}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
import{S as s,i as a,s as r,j as t,m as e,o as n,G as f,v as o,r as m,w as u,z as i}from"../chunks/vendor-a9bf48e1.js";import{V as c,i as $}from"../chunks/util-fb52efd4.js";function d(s){let a,r;return a=new c({}),{c(){t(a.$$.fragment)},l(s){e(a.$$.fragment,s)},m(s,t){n(a,s,t),r=!0},p:f,i(s){r||(o(a.$$.fragment,s),r=!0)},o(s){m(a.$$.fragment,s),r=!1},d(s){u(a,s)}}}function l(s){return i($),[]}export default class extends s{constructor(s){super(),a(this,s,l,d,r,{})}}
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,85 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<title>Online FlowChart & Diagrams Editor - Mermaid Live Editor</title>
|
||||||
|
<meta
|
||||||
|
name="og:image"
|
||||||
|
content="https://github.com/mermaid-js/mermaid/raw/develop/img/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."
|
||||||
|
/>
|
||||||
|
<link rel="icon" type="image/png" href="favicon.png" />
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/css/all.min.css"
|
||||||
|
/>
|
||||||
|
<script
|
||||||
|
src="https://cdn.jsdelivr.net/npm/mermaid@8.10.1/dist/mermaid.min.js"
|
||||||
|
integrity="sha256-aQCGsx3/OLAXwNyOUrAedielIQAjIrMFkcWdXMlIkGc="
|
||||||
|
crossorigin="anonymous"
|
||||||
|
></script>
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.23.0/min/vs/editor/editor.main.min.css"
|
||||||
|
integrity="sha512-RhnuJxgda82cBylRysVDqdpwnBcSkMzxz1+BxGwBPNMzBJlvaOjHz7P2kXELC0bdNxazsNSyJb7KAww0T5iUdQ=="
|
||||||
|
crossorigin="anonymous"
|
||||||
|
referrerpolicy="no-referrer"
|
||||||
|
/>
|
||||||
|
<script>
|
||||||
|
var require = {
|
||||||
|
paths: { vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.23.0/min/vs' }
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<script
|
||||||
|
src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.23.0/min/vs/loader.min.js"
|
||||||
|
integrity="sha512-+8+MX2hyUZxaUfMJT0ew+rPsrTGiTmCg8oksa6uVE/ZlR/g3SJtyozqcqDGkw/W785xYAvcx1LxXPP+ywD0SNw=="
|
||||||
|
crossorigin="anonymous"
|
||||||
|
referrerpolicy="no-referrer"
|
||||||
|
></script>
|
||||||
|
<script
|
||||||
|
src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.23.0/min/vs/editor/editor.main.nls.min.js"
|
||||||
|
integrity="sha512-3aAqsDS5ClTlwyzxufRhW9WMwZlYn3V8GLRl324pMIftp+CA6kvxfjlm8TG7Wi53eBcerEdX0YfXm3QLvf1Pqg=="
|
||||||
|
crossorigin="anonymous"
|
||||||
|
referrerpolicy="no-referrer"
|
||||||
|
></script>
|
||||||
|
<script
|
||||||
|
src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.23.0/min/vs/editor/editor.main.js"
|
||||||
|
integrity="sha512-sOJZBKiSvh/6vxIimdXkjO45Nd3v2n3ZYtrwktgj5SJh0+PCqNQ5oqzxEr6c/o4ULczn1Wo2yh1qrz+ghduDUA=="
|
||||||
|
crossorigin="anonymous"
|
||||||
|
referrerpolicy="no-referrer"
|
||||||
|
></script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<link rel="modulepreload" href="/mermaid-svelte-kit/_app/start-6a449612.js">
|
||||||
|
<link rel="modulepreload" href="/mermaid-svelte-kit/_app/chunks/vendor-a9bf48e1.js">
|
||||||
|
<link rel="modulepreload" href="/mermaid-svelte-kit/_app/chunks/singletons-bb9012b7.js">
|
||||||
|
<link rel="modulepreload" href="/mermaid-svelte-kit/_app/chunks/paths-45dac81d.js">
|
||||||
|
<link rel="stylesheet" href="/mermaid-svelte-kit/_app/assets/start-0826e215.css">
|
||||||
|
|
||||||
|
<script type="module">
|
||||||
|
import { start } from "/mermaid-svelte-kit/_app/start-6a449612.js";
|
||||||
|
start({
|
||||||
|
target: document.querySelector("#svelte"),
|
||||||
|
paths: {"base":"/mermaid-svelte-kit","assets":"/mermaid-svelte-kit"},
|
||||||
|
session: {},
|
||||||
|
host: location.host,
|
||||||
|
route: true,
|
||||||
|
spa: true,
|
||||||
|
hydrate: null
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="svelte">
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
@@ -0,0 +1,85 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<title>Online FlowChart & Diagrams Editor - Mermaid Live Editor</title>
|
||||||
|
<meta
|
||||||
|
name="og:image"
|
||||||
|
content="https://github.com/mermaid-js/mermaid/raw/develop/img/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."
|
||||||
|
/>
|
||||||
|
<link rel="icon" type="image/png" href="favicon.png" />
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/css/all.min.css"
|
||||||
|
/>
|
||||||
|
<script
|
||||||
|
src="https://cdn.jsdelivr.net/npm/mermaid@8.10.1/dist/mermaid.min.js"
|
||||||
|
integrity="sha256-aQCGsx3/OLAXwNyOUrAedielIQAjIrMFkcWdXMlIkGc="
|
||||||
|
crossorigin="anonymous"
|
||||||
|
></script>
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.23.0/min/vs/editor/editor.main.min.css"
|
||||||
|
integrity="sha512-RhnuJxgda82cBylRysVDqdpwnBcSkMzxz1+BxGwBPNMzBJlvaOjHz7P2kXELC0bdNxazsNSyJb7KAww0T5iUdQ=="
|
||||||
|
crossorigin="anonymous"
|
||||||
|
referrerpolicy="no-referrer"
|
||||||
|
/>
|
||||||
|
<script>
|
||||||
|
var require = {
|
||||||
|
paths: { vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.23.0/min/vs' }
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<script
|
||||||
|
src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.23.0/min/vs/loader.min.js"
|
||||||
|
integrity="sha512-+8+MX2hyUZxaUfMJT0ew+rPsrTGiTmCg8oksa6uVE/ZlR/g3SJtyozqcqDGkw/W785xYAvcx1LxXPP+ywD0SNw=="
|
||||||
|
crossorigin="anonymous"
|
||||||
|
referrerpolicy="no-referrer"
|
||||||
|
></script>
|
||||||
|
<script
|
||||||
|
src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.23.0/min/vs/editor/editor.main.nls.min.js"
|
||||||
|
integrity="sha512-3aAqsDS5ClTlwyzxufRhW9WMwZlYn3V8GLRl324pMIftp+CA6kvxfjlm8TG7Wi53eBcerEdX0YfXm3QLvf1Pqg=="
|
||||||
|
crossorigin="anonymous"
|
||||||
|
referrerpolicy="no-referrer"
|
||||||
|
></script>
|
||||||
|
<script
|
||||||
|
src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.23.0/min/vs/editor/editor.main.js"
|
||||||
|
integrity="sha512-sOJZBKiSvh/6vxIimdXkjO45Nd3v2n3ZYtrwktgj5SJh0+PCqNQ5oqzxEr6c/o4ULczn1Wo2yh1qrz+ghduDUA=="
|
||||||
|
crossorigin="anonymous"
|
||||||
|
referrerpolicy="no-referrer"
|
||||||
|
></script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<link rel="modulepreload" href="/mermaid-svelte-kit/_app/start-6a449612.js">
|
||||||
|
<link rel="modulepreload" href="/mermaid-svelte-kit/_app/chunks/vendor-a9bf48e1.js">
|
||||||
|
<link rel="modulepreload" href="/mermaid-svelte-kit/_app/chunks/singletons-bb9012b7.js">
|
||||||
|
<link rel="modulepreload" href="/mermaid-svelte-kit/_app/chunks/paths-45dac81d.js">
|
||||||
|
<link rel="stylesheet" href="/mermaid-svelte-kit/_app/assets/start-0826e215.css">
|
||||||
|
|
||||||
|
<script type="module">
|
||||||
|
import { start } from "/mermaid-svelte-kit/_app/start-6a449612.js";
|
||||||
|
start({
|
||||||
|
target: document.querySelector("#svelte"),
|
||||||
|
paths: {"base":"/mermaid-svelte-kit","assets":"/mermaid-svelte-kit"},
|
||||||
|
session: {},
|
||||||
|
host: location.host,
|
||||||
|
route: true,
|
||||||
|
spa: true,
|
||||||
|
hydrate: null
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="svelte">
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# https://www.robotstxt.org/robotstxt.html
|
||||||
|
User-agent: *
|
||||||
|
Disallow:
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<title>Online FlowChart & Diagrams Editor - Mermaid Live Editor</title>
|
||||||
|
<meta
|
||||||
|
name="og:image"
|
||||||
|
content="https://github.com/mermaid-js/mermaid/raw/develop/img/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."
|
||||||
|
/>
|
||||||
|
<link rel="icon" type="image/png" href="favicon.png" />
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/css/all.min.css"
|
||||||
|
/>
|
||||||
|
<script
|
||||||
|
src="https://cdn.jsdelivr.net/npm/mermaid@8.10.1/dist/mermaid.min.js"
|
||||||
|
integrity="sha256-aQCGsx3/OLAXwNyOUrAedielIQAjIrMFkcWdXMlIkGc="
|
||||||
|
crossorigin="anonymous"
|
||||||
|
></script>
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.23.0/min/vs/editor/editor.main.min.css"
|
||||||
|
integrity="sha512-RhnuJxgda82cBylRysVDqdpwnBcSkMzxz1+BxGwBPNMzBJlvaOjHz7P2kXELC0bdNxazsNSyJb7KAww0T5iUdQ=="
|
||||||
|
crossorigin="anonymous"
|
||||||
|
referrerpolicy="no-referrer"
|
||||||
|
/>
|
||||||
|
<script>
|
||||||
|
var require = {
|
||||||
|
paths: { vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.23.0/min/vs' }
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<script
|
||||||
|
src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.23.0/min/vs/loader.min.js"
|
||||||
|
integrity="sha512-+8+MX2hyUZxaUfMJT0ew+rPsrTGiTmCg8oksa6uVE/ZlR/g3SJtyozqcqDGkw/W785xYAvcx1LxXPP+ywD0SNw=="
|
||||||
|
crossorigin="anonymous"
|
||||||
|
referrerpolicy="no-referrer"
|
||||||
|
></script>
|
||||||
|
<script
|
||||||
|
src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.23.0/min/vs/editor/editor.main.nls.min.js"
|
||||||
|
integrity="sha512-3aAqsDS5ClTlwyzxufRhW9WMwZlYn3V8GLRl324pMIftp+CA6kvxfjlm8TG7Wi53eBcerEdX0YfXm3QLvf1Pqg=="
|
||||||
|
crossorigin="anonymous"
|
||||||
|
referrerpolicy="no-referrer"
|
||||||
|
></script>
|
||||||
|
<script
|
||||||
|
src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.23.0/min/vs/editor/editor.main.js"
|
||||||
|
integrity="sha512-sOJZBKiSvh/6vxIimdXkjO45Nd3v2n3ZYtrwktgj5SJh0+PCqNQ5oqzxEr6c/o4ULczn1Wo2yh1qrz+ghduDUA=="
|
||||||
|
crossorigin="anonymous"
|
||||||
|
referrerpolicy="no-referrer"
|
||||||
|
></script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<link rel="modulepreload" href="/mermaid-svelte-kit/_app/start-6a449612.js">
|
||||||
|
<link rel="modulepreload" href="/mermaid-svelte-kit/_app/chunks/vendor-a9bf48e1.js">
|
||||||
|
<link rel="modulepreload" href="/mermaid-svelte-kit/_app/chunks/singletons-bb9012b7.js">
|
||||||
|
<link rel="modulepreload" href="/mermaid-svelte-kit/_app/chunks/paths-45dac81d.js">
|
||||||
|
<link rel="stylesheet" href="/mermaid-svelte-kit/_app/assets/start-0826e215.css">
|
||||||
|
|
||||||
|
<script type="module">
|
||||||
|
import { start } from "/mermaid-svelte-kit/_app/start-6a449612.js";
|
||||||
|
start({
|
||||||
|
target: document.querySelector("#svelte"),
|
||||||
|
paths: {"base":"/mermaid-svelte-kit","assets":"/mermaid-svelte-kit"},
|
||||||
|
session: {},
|
||||||
|
host: location.host,
|
||||||
|
route: true,
|
||||||
|
spa: true,
|
||||||
|
hydrate: null
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="svelte">
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"name": "~TODO~",
|
||||||
|
"version": "0.0.9",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "svelte-kit dev",
|
||||||
|
"build": "svelte-kit build",
|
||||||
|
"preview": "svelte-kit preview",
|
||||||
|
"lint": "prettier --check --plugin-search-dir=. . && eslint --ignore-path .gitignore .",
|
||||||
|
"format": "prettier --write --plugin-search-dir=. ."
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@sveltejs/adapter-static": "^1.0.0-next.11",
|
||||||
|
"@sveltejs/kit": "next",
|
||||||
|
"@types/mermaid": "^8.2.5",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^4.19.0",
|
||||||
|
"@typescript-eslint/parser": "^4.19.0",
|
||||||
|
"autoprefixer": "^10.2.5",
|
||||||
|
"cssnano": "^5.0.1",
|
||||||
|
"eslint": "^7.22.0",
|
||||||
|
"eslint-config-prettier": "^8.1.0",
|
||||||
|
"eslint-plugin-svelte3": "^3.2.0",
|
||||||
|
"postcss": "^8.2.10",
|
||||||
|
"postcss-load-config": "^3.0.1",
|
||||||
|
"prettier": "~2.2.1",
|
||||||
|
"prettier-plugin-svelte": "^2.2.0",
|
||||||
|
"svelte": "^3.34.0",
|
||||||
|
"svelte-preprocess": "^4.7.1",
|
||||||
|
"tailwindcss": "^2.1.1",
|
||||||
|
"tslib": "^2.0.0",
|
||||||
|
"typescript": "^4.0.0"
|
||||||
|
},
|
||||||
|
"type": "module",
|
||||||
|
"dependencies": {
|
||||||
|
"@fontsource/fira-mono": "^4.2.2",
|
||||||
|
"@lukeed/uuid": "^2.0.0",
|
||||||
|
"@macfja/svelte-persistent-store": "^1.1.0",
|
||||||
|
"@tailwindcss/forms": "^0.3.2",
|
||||||
|
"cookie": "^0.4.1",
|
||||||
|
"js-base64": "https://github.com/sidharthv96/js-base64#patch-1",
|
||||||
|
"mermaid": "^8.10.1",
|
||||||
|
"moment": "^2.29.1",
|
||||||
|
"monaco-editor": "^0.24.0",
|
||||||
|
"random-word-slugs": "^0.0.2",
|
||||||
|
"svelte-watch-resize": "^1.0.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
const tailwindcss = require("tailwindcss");
|
||||||
|
const autoprefixer = require("autoprefixer");
|
||||||
|
const cssnano = require("cssnano");
|
||||||
|
|
||||||
|
const mode = process.env.NODE_ENV;
|
||||||
|
const dev = mode === "development";
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
plugins: [
|
||||||
|
// Some plugins, like postcss-nested, need to run before Tailwind
|
||||||
|
|
||||||
|
tailwindcss,
|
||||||
|
|
||||||
|
// But others, like autoprefixer, need to run after
|
||||||
|
|
||||||
|
autoprefixer,
|
||||||
|
|
||||||
|
!dev && cssnano({
|
||||||
|
preset: "default",
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
};
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<title>Online FlowChart & Diagrams Editor - Mermaid Live Editor</title>
|
||||||
|
<meta
|
||||||
|
name="og:image"
|
||||||
|
content="https://github.com/mermaid-js/mermaid/raw/develop/img/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."
|
||||||
|
/>
|
||||||
|
<link rel="icon" type="image/png" href="favicon.png" />
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/css/all.min.css"
|
||||||
|
/>
|
||||||
|
<script
|
||||||
|
src="https://cdn.jsdelivr.net/npm/mermaid@8.10.1/dist/mermaid.min.js"
|
||||||
|
integrity="sha256-aQCGsx3/OLAXwNyOUrAedielIQAjIrMFkcWdXMlIkGc="
|
||||||
|
crossorigin="anonymous"
|
||||||
|
></script>
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.23.0/min/vs/editor/editor.main.min.css"
|
||||||
|
integrity="sha512-RhnuJxgda82cBylRysVDqdpwnBcSkMzxz1+BxGwBPNMzBJlvaOjHz7P2kXELC0bdNxazsNSyJb7KAww0T5iUdQ=="
|
||||||
|
crossorigin="anonymous"
|
||||||
|
referrerpolicy="no-referrer"
|
||||||
|
/>
|
||||||
|
<script>
|
||||||
|
var require = {
|
||||||
|
paths: { vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.23.0/min/vs' }
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<script
|
||||||
|
src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.23.0/min/vs/loader.min.js"
|
||||||
|
integrity="sha512-+8+MX2hyUZxaUfMJT0ew+rPsrTGiTmCg8oksa6uVE/ZlR/g3SJtyozqcqDGkw/W785xYAvcx1LxXPP+ywD0SNw=="
|
||||||
|
crossorigin="anonymous"
|
||||||
|
referrerpolicy="no-referrer"
|
||||||
|
></script>
|
||||||
|
<script
|
||||||
|
src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.23.0/min/vs/editor/editor.main.nls.min.js"
|
||||||
|
integrity="sha512-3aAqsDS5ClTlwyzxufRhW9WMwZlYn3V8GLRl324pMIftp+CA6kvxfjlm8TG7Wi53eBcerEdX0YfXm3QLvf1Pqg=="
|
||||||
|
crossorigin="anonymous"
|
||||||
|
referrerpolicy="no-referrer"
|
||||||
|
></script>
|
||||||
|
<script
|
||||||
|
src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.23.0/min/vs/editor/editor.main.js"
|
||||||
|
integrity="sha512-sOJZBKiSvh/6vxIimdXkjO45Nd3v2n3ZYtrwktgj5SJh0+PCqNQ5oqzxEr6c/o4ULczn1Wo2yh1qrz+ghduDUA=="
|
||||||
|
crossorigin="anonymous"
|
||||||
|
referrerpolicy="no-referrer"
|
||||||
|
></script>
|
||||||
|
%svelte.head%
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="svelte">%svelte.body%</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@import '@fontsource/fira-mono';
|
||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
Vendored
+33
@@ -0,0 +1,33 @@
|
|||||||
|
/// <reference types="@sveltejs/kit" />
|
||||||
|
|
||||||
|
interface EditorUpdateEvent {
|
||||||
|
text: string;
|
||||||
|
}
|
||||||
|
interface EditorEvents {
|
||||||
|
update: EditorUpdateEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TabEvents {
|
||||||
|
select: Tab;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Tab {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
icon: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface State {
|
||||||
|
code: string;
|
||||||
|
mermaid: string;
|
||||||
|
updateEditor: boolean;
|
||||||
|
updateDiagram: boolean;
|
||||||
|
autoSync: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface HistoryEntry {
|
||||||
|
state: State;
|
||||||
|
time: number;
|
||||||
|
name?: string;
|
||||||
|
auto: boolean;
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import cookie from 'cookie';
|
||||||
|
import { v4 as uuid } from '@lukeed/uuid';
|
||||||
|
import type { Handle } from '@sveltejs/kit';
|
||||||
|
|
||||||
|
export const handle: Handle = async ({ request, render }) => {
|
||||||
|
const cookies = cookie.parse(request.headers.cookie || '');
|
||||||
|
request.locals.userid = cookies.userid || uuid();
|
||||||
|
|
||||||
|
// TODO https://github.com/sveltejs/kit/issues/1046
|
||||||
|
if (request.query.has('_method')) {
|
||||||
|
request.method = request.query.get('_method').toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await render(request);
|
||||||
|
|
||||||
|
if (!cookies.userid) {
|
||||||
|
// if this is the first time the user has visited this app,
|
||||||
|
// set a cookie so that we recognise them when they return
|
||||||
|
response.headers['set-cookie'] = `userid=${request.locals.userid}; Path=/; HttpOnly`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
};
|
||||||
@@ -0,0 +1,168 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import Card from '$lib/components/card/card.svelte';
|
||||||
|
import { base64State } from '$lib/util/state';
|
||||||
|
|
||||||
|
import { toBase64 } from 'js-base64';
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
type Exporter = (
|
||||||
|
canvas: HTMLCanvasElement,
|
||||||
|
context: CanvasRenderingContext2D,
|
||||||
|
image: HTMLImageElement
|
||||||
|
) => () => void;
|
||||||
|
|
||||||
|
const getBase64SVG = (): string => {
|
||||||
|
const container: HTMLElement = document.getElementById('container');
|
||||||
|
const svg = container.innerHTML.replaceAll('<br>', '<br/>');
|
||||||
|
return toBase64(svg);
|
||||||
|
};
|
||||||
|
|
||||||
|
const exportImage = (event: Event, exporter: Exporter) => {
|
||||||
|
const canvas: HTMLCanvasElement = document.createElement('canvas');
|
||||||
|
const svg: HTMLElement = document.querySelector('#container svg');
|
||||||
|
debugger;
|
||||||
|
const box: DOMRect = svg.getBoundingClientRect();
|
||||||
|
canvas.width = box.width;
|
||||||
|
canvas.height = box.height;
|
||||||
|
if (imagemodeselected === 'width') {
|
||||||
|
const ratio = box.height / box.width;
|
||||||
|
canvas.width = userimagesize;
|
||||||
|
canvas.height = userimagesize * ratio;
|
||||||
|
} else if (imagemodeselected === 'height') {
|
||||||
|
const ratio = box.width / box.height;
|
||||||
|
canvas.width = userimagesize * ratio;
|
||||||
|
canvas.height = userimagesize;
|
||||||
|
}
|
||||||
|
const context = canvas.getContext('2d');
|
||||||
|
context.fillStyle = 'white';
|
||||||
|
context.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
const image = new Image();
|
||||||
|
image.onload = exporter(canvas, context, image);
|
||||||
|
|
||||||
|
image.src = `data:image/svg+xml;base64,${getBase64SVG()}`;
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
};
|
||||||
|
|
||||||
|
const simulateDownload = (download: string, href: string): void => {
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.download = download;
|
||||||
|
a.href = href;
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
};
|
||||||
|
const downloadImage: Exporter = (canvas, context, image) => {
|
||||||
|
return () => {
|
||||||
|
context.drawImage(image, 0, 0, canvas.width, canvas.height);
|
||||||
|
simulateDownload(
|
||||||
|
`mermaid-diagram-${moment().format('YYYYMMDDHHmmss')}.png`,
|
||||||
|
canvas.toDataURL('image/png').replace('image/png', 'image/octet-stream')
|
||||||
|
);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const isClipboardAvailable = () => {
|
||||||
|
return window?.hasOwnProperty('ClipboardItem');
|
||||||
|
};
|
||||||
|
|
||||||
|
const clipboardCopy: Exporter = (canvas, context, image) => {
|
||||||
|
return () => {
|
||||||
|
context.drawImage(image, 0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
canvas.toBlob((blob) => {
|
||||||
|
try {
|
||||||
|
// @ts-ignore
|
||||||
|
navigator.clipboard.write([
|
||||||
|
// @ts-ignore
|
||||||
|
new ClipboardItem({
|
||||||
|
[blob.type]: blob
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const onCopyClipboard = (event) => {
|
||||||
|
exportImage(event, clipboardCopy);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDownloadPNG = (event) => {
|
||||||
|
exportImage(event, downloadImage);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDownloadSVG = (event) => {
|
||||||
|
simulateDownload(
|
||||||
|
`mermaid-diagram-${moment().format('YYYYMMDDHHmmss')}.svg`,
|
||||||
|
`data:image/svg+xml;base64,${getBase64SVG()}`
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onCopyMarkdown = (event) => {
|
||||||
|
event.target.select();
|
||||||
|
document.execCommand('Copy');
|
||||||
|
};
|
||||||
|
|
||||||
|
let iUrl;
|
||||||
|
let svgUrl;
|
||||||
|
let mdCode;
|
||||||
|
let imagemodeselected = 'auto';
|
||||||
|
let userimagesize = 1080;
|
||||||
|
|
||||||
|
const unsubscribe = base64State.subscribe((b64Code) => {
|
||||||
|
iUrl = `https://mermaid.ink/img/${b64Code}`;
|
||||||
|
svgUrl = `https://mermaid.ink/svg/${b64Code}`;
|
||||||
|
mdCode = `[](${window.location.protocol}//${window.location.host}${window.location.pathname}/edit#${b64Code})`;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Card title="Actions" isOpen={false}>
|
||||||
|
<div class="flex flex-wrap gap-2 m-2">
|
||||||
|
{#if isClipboardAvailable()}
|
||||||
|
<button class="btn w-full" on:click={onCopyClipboard}
|
||||||
|
><i class="far fa-copy" /> Copy Image to clipboard
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
<button class="btn flex-auto" on:click={onDownloadPNG}>
|
||||||
|
<i class="fas fa-download" /> PNG
|
||||||
|
</button>
|
||||||
|
<button class="btn flex-auto" on:click={onDownloadSVG}>
|
||||||
|
<i class="fas fa-download" /> SVG
|
||||||
|
</button>
|
||||||
|
<button class="btn flex-auto">
|
||||||
|
<a class="link-style" target="_blank" href={iUrl}
|
||||||
|
><i class="fas fa-external-link-alt" /> PNG</a>
|
||||||
|
</button>
|
||||||
|
<button class="btn flex-auto">
|
||||||
|
<a class="link-style" target="_blank" href={svgUrl}
|
||||||
|
><i class="fas fa-external-link-alt" /> SVG</a>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="flex gap-2 items-center">
|
||||||
|
PNG size
|
||||||
|
<input type="radio" value="auto" id="autosize" bind:group={imagemodeselected} />
|
||||||
|
<label for="autosize">Auto</label>
|
||||||
|
<input type="radio" value="width" id="width-active" bind:group={imagemodeselected} />
|
||||||
|
<label for="width">Width</label>
|
||||||
|
<input type="radio" value="height" id="height-active" bind:group={imagemodeselected} />
|
||||||
|
<label for="height">Height</label>
|
||||||
|
{#if imagemodeselected !== 'auto'}
|
||||||
|
<input id="height" type="number" min="3" max="10000" bind:value={userimagesize} />
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="w-full flex gap-2 items-center">
|
||||||
|
<label for="markdown">Copy Markdown</label>
|
||||||
|
<input class="flex-1" id="markdown" type="text" value={mdCode} on:click={onCopyMarkdown} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.btn {
|
||||||
|
@apply rounded p-2 bg-indigo-400 shadow flex-auto text-white hover:bg-indigo-500;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { slide } from 'svelte/transition';
|
||||||
|
import Tabs from './tabs.svelte';
|
||||||
|
export let isCloseable: boolean = true;
|
||||||
|
export let isOpen: boolean = true;
|
||||||
|
export let tabs: Tab[] = [];
|
||||||
|
export let title: string;
|
||||||
|
$: isOpen = isCloseable ? isOpen : true;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class={`bg-white rounded overflow-hidden shadow m-2 flex-grow flex flex-col `}>
|
||||||
|
<div class="bg-indigo-400 border-gray-400 p-2 flex-none" on:click={() => (isOpen = !isOpen)}>
|
||||||
|
<div class="flex justify-between">
|
||||||
|
<Tabs on:select {tabs} bind:isOpen {title} {isCloseable} />
|
||||||
|
<div class="flex gap-x-4 items-center text-white">
|
||||||
|
<slot name="actions" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{#if isOpen}
|
||||||
|
<div class="flex-grow overflow-auto" transition:slide>
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { createEventDispatcher } from 'svelte';
|
||||||
|
import { fade } from 'svelte/transition';
|
||||||
|
export let isCloseable: boolean = true;
|
||||||
|
export let tabs: Tab[] = [];
|
||||||
|
export let title: string;
|
||||||
|
export let isOpen = false;
|
||||||
|
|
||||||
|
let activeTabID: string = tabs[0]?.id;
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher<TabEvents>();
|
||||||
|
const toggleTabs = (tab: Tab) => {
|
||||||
|
activeTabID = tab.id;
|
||||||
|
dispatch('select', tab);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex cursor-default">
|
||||||
|
<span class="text-white mr-2 font-semibold" on:click|stopPropagation={() => (isOpen = !isOpen)}>
|
||||||
|
{#if isCloseable}
|
||||||
|
<svg
|
||||||
|
class="inline"
|
||||||
|
class:isOpen
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="12"
|
||||||
|
height="7"
|
||||||
|
viewBox="0 0 12 7"
|
||||||
|
><defs
|
||||||
|
><style>
|
||||||
|
.cls-1 {
|
||||||
|
fill: #fff;
|
||||||
|
fill-rule: evenodd;
|
||||||
|
}
|
||||||
|
</style></defs
|
||||||
|
><path
|
||||||
|
class="cls-1"
|
||||||
|
d="M10.38.45,6,4.83,1.56.39h0A.84.84,0,0,0,.38,1.57h0l5,5h0a.83.83,0,0,0,.6.26H6a.83.83,0,0,0,.6-.26h0l5-5h0A.84.84,0,1,0,10.38.45Z" /></svg>
|
||||||
|
{/if}
|
||||||
|
{title}</span>
|
||||||
|
{#if isOpen && tabs}
|
||||||
|
<ul class="flex flex-wrap flex-row" transition:fade>
|
||||||
|
{#each tabs as tab}
|
||||||
|
<li class="mr-2 last:mr-0 w-28 flex-auto text-center">
|
||||||
|
<div
|
||||||
|
class="text cursor-pointer font-semibold min-w-16 w-auto px-2 py-1 -mb-4 rounded-t block leading-normal {activeTabID ===
|
||||||
|
tab.id
|
||||||
|
? 'text-indigo-500 bg-white border-white'
|
||||||
|
: 'text-white bg-indigo-500 border-indigo-500 hover:bg-indigo-600'}"
|
||||||
|
on:click|stopPropagation={() => toggleTabs(tab)}>
|
||||||
|
<i class={tab.icon} />
|
||||||
|
{tab.title}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.isOpen {
|
||||||
|
transform: rotate(-90deg);
|
||||||
|
transition-duration: 0.5s;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type monaco from 'monaco-editor';
|
||||||
|
import { createEventDispatcher, onMount } from 'svelte';
|
||||||
|
import { initEditor } from './util';
|
||||||
|
|
||||||
|
let divEl: HTMLDivElement = null;
|
||||||
|
let editor: monaco.editor.IStandaloneCodeEditor;
|
||||||
|
let Monaco;
|
||||||
|
|
||||||
|
export let text: string;
|
||||||
|
export let language: string;
|
||||||
|
export let editorOptions: monaco.editor.IStandaloneEditorConstructionOptions = {
|
||||||
|
value: text,
|
||||||
|
language: language,
|
||||||
|
scrollBeyondLastLine: false,
|
||||||
|
minimap: {
|
||||||
|
enabled: false
|
||||||
|
},
|
||||||
|
overviewRulerLanes: 0
|
||||||
|
};
|
||||||
|
export let errorMarkers: monaco.editor.IMarkerData[] = [];
|
||||||
|
$: Monaco?.editor.setModelLanguage(editor.getModel(), language);
|
||||||
|
$: editor?.setValue(text);
|
||||||
|
$: {
|
||||||
|
Monaco?.editor.setModelMarkers(editor.getModel(), 'test', errorMarkers);
|
||||||
|
}
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher<EditorEvents>();
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
//@ts-ignore
|
||||||
|
Monaco = monaco; // This is a hack to handle a svelte-kit error when importing monaco.
|
||||||
|
initEditor(Monaco);
|
||||||
|
|
||||||
|
editor = Monaco.editor.create(divEl, editorOptions);
|
||||||
|
editor.onDidChangeModelContent(async () => {
|
||||||
|
dispatch('update', {
|
||||||
|
text: editor.getValue()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const resizeObserver = new ResizeObserver((entries) => {
|
||||||
|
editor.layout({
|
||||||
|
height: entries[0].contentRect.height,
|
||||||
|
width: entries[0].contentRect.width
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
resizeObserver.observe(divEl.parentElement);
|
||||||
|
return () => {
|
||||||
|
editor.dispose();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div bind:this={divEl} class="overflow-hidden" />
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
export const initEditor = (monaco) => {
|
||||||
|
monaco.languages.register({ id: 'mermaid' });
|
||||||
|
|
||||||
|
// Register a tokens provider for the language
|
||||||
|
monaco.languages.setMonarchTokensProvider('mermaid', {
|
||||||
|
typeKeywords: [
|
||||||
|
'graph',
|
||||||
|
'stateDiagram',
|
||||||
|
'sequenceDiagram',
|
||||||
|
'classDiagram',
|
||||||
|
'pie',
|
||||||
|
'flowchart',
|
||||||
|
'gantt'
|
||||||
|
],
|
||||||
|
keywords: ['patricipant', 'as'],
|
||||||
|
arrows: ['---', '===', '-->', '==>'],
|
||||||
|
|
||||||
|
tokenizer: {
|
||||||
|
root: [
|
||||||
|
[/[{}]/, 'delimiter.bracket'],
|
||||||
|
[/[a-z_$][\w$]*/, { cases: { '@typeKeywords': 'keyword', '@keywords': 'keyword' } }],
|
||||||
|
[/[-=>ox]+/, { cases: { '@arrows': 'transition' } }],
|
||||||
|
[/[\[\{\(}]+.+?[\)\]\}]+/, 'string'],
|
||||||
|
[/\".*\"/, 'string']
|
||||||
|
]
|
||||||
|
},
|
||||||
|
whitespace: [
|
||||||
|
[/[ \t\r\n]+/, 'white'],
|
||||||
|
[/\%\%.*$/, 'comment']
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
monaco.editor.defineTheme('myCoolTheme', {
|
||||||
|
base: 'vs',
|
||||||
|
inherit: false,
|
||||||
|
rules: [
|
||||||
|
{ token: 'keyword', foreground: '880000', fontStyle: 'bold' },
|
||||||
|
{ token: 'custom-error', foreground: 'ff0000', fontStyle: 'bold' },
|
||||||
|
{ token: 'string', foreground: 'AA8500' },
|
||||||
|
{ token: 'transition', foreground: '008800', fontStyle: 'bold' },
|
||||||
|
{ token: 'delimiter.bracket', foreground: '000000', fontStyle: 'bold' }
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Register a completion item provider for the new language
|
||||||
|
monaco.languages.registerCompletionItemProvider('mermaid', {
|
||||||
|
provideCompletionItems: () => {
|
||||||
|
var suggestions = [
|
||||||
|
{
|
||||||
|
label: 'simpleText',
|
||||||
|
kind: monaco.languages.CompletionItemKind.Text,
|
||||||
|
insertText: 'simpleText'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'testing',
|
||||||
|
kind: monaco.languages.CompletionItemKind.Keyword,
|
||||||
|
insertText: 'testing(${1:condition})',
|
||||||
|
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'ifelse',
|
||||||
|
kind: monaco.languages.CompletionItemKind.Snippet,
|
||||||
|
insertText: ['if (${1:condition}) {', '\t$0', '} else {', '\t', '}'].join('\n'),
|
||||||
|
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
|
||||||
|
documentation: 'If-Else Statement'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
return { suggestions: suggestions };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import Card from '$lib/components/card/card.svelte';
|
||||||
|
import { codeStore, getStateString } from '$lib/util/state';
|
||||||
|
import {
|
||||||
|
addHistoryEntry,
|
||||||
|
autoHistoryMode,
|
||||||
|
clearHistoryData,
|
||||||
|
getPreviousState,
|
||||||
|
historyStore
|
||||||
|
} from './history';
|
||||||
|
import { notify, prompt } from '$lib/util/notify';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
const HISTORY_SAVE_INTERVAL: number = 60000;
|
||||||
|
|
||||||
|
const tabSelectHandler = (message: CustomEvent<Tab>) => {
|
||||||
|
autoHistoryMode.set('timeline' === message.detail.id);
|
||||||
|
};
|
||||||
|
const tabs: Tab[] = [
|
||||||
|
{
|
||||||
|
id: 'saved',
|
||||||
|
title: 'Saved',
|
||||||
|
icon: 'far fa-bookmark'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'timeline',
|
||||||
|
title: 'Timeline',
|
||||||
|
icon: 'fas fa-history'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const saveHistory = (auto = false) => {
|
||||||
|
const currentState: string = getStateString();
|
||||||
|
const previousState: string = getPreviousState(auto);
|
||||||
|
if (previousState !== currentState) {
|
||||||
|
addHistoryEntry({
|
||||||
|
state: $codeStore,
|
||||||
|
time: Date.now(),
|
||||||
|
auto
|
||||||
|
});
|
||||||
|
} else if (!auto) {
|
||||||
|
notify('State already saved.');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const clearHistory = (date?: number): void => {
|
||||||
|
if (!date && !prompt('Clear all saved items?')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
clearHistoryData(date);
|
||||||
|
};
|
||||||
|
|
||||||
|
const restoreHistory = (state: State): void => {
|
||||||
|
codeStore.set({ ...state, updateEditor: true, updateDiagram: true });
|
||||||
|
};
|
||||||
|
|
||||||
|
const relativeTime = (time: number) => {
|
||||||
|
const t = new Date(time);
|
||||||
|
return `${new Date(t).toLocaleString()} (${moment(t).fromNow()})`;
|
||||||
|
};
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
autoHistoryMode.set(false);
|
||||||
|
setInterval(() => {
|
||||||
|
saveHistory(true);
|
||||||
|
}, HISTORY_SAVE_INTERVAL);
|
||||||
|
});
|
||||||
|
|
||||||
|
let isOpen = true;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Card on:select={tabSelectHandler} bind:isOpen {tabs} title="History">
|
||||||
|
<div slot="actions">
|
||||||
|
<button class="btn" on:click|stopPropagation={() => saveHistory()} title="Save current state"
|
||||||
|
><i class="far fa-save" /></button>
|
||||||
|
<button
|
||||||
|
class="btn text-red-400"
|
||||||
|
on:click|stopPropagation={() => clearHistory()}
|
||||||
|
title="Delete all saved states"><i class="fas fa-trash-alt" /></button>
|
||||||
|
</div>
|
||||||
|
<ul class="p-2 space-y-2 overflow-auto h-56">
|
||||||
|
{#each $historyStore as { state, time, name }}
|
||||||
|
<li class="rounded p-2 shadow flex-col">
|
||||||
|
<div class="flex">
|
||||||
|
<div class="flex-1">
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<span>{name}</span>
|
||||||
|
<span class="text-gray-400 text-sm">{relativeTime(time)}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex gap-2 content-center">
|
||||||
|
<button
|
||||||
|
class="rounded px-2 w-24 bg-green-200 hover:bg-green-300"
|
||||||
|
on:click={() => restoreHistory(state)}><i class="fas fa-undo" /> Restore</button>
|
||||||
|
<button
|
||||||
|
class="rounded px-2 w-24 bg-red-200 hover:bg-red-300"
|
||||||
|
on:click={() => clearHistory(time)}><i class="fas fa-trash-alt" /> Delete</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<style lang="postcss">
|
||||||
|
.btn {
|
||||||
|
@apply bg-indigo-500 hover:bg-indigo-700 rounded px-4 shadow;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import { derived, Readable, Writable, writable, get } from 'svelte/store';
|
||||||
|
import { persist, localStorage } from '@macfja/svelte-persistent-store';
|
||||||
|
import { generateSlug } from 'random-word-slugs';
|
||||||
|
|
||||||
|
const MAX_AUTO_HISTORY_LENGTH = 30;
|
||||||
|
|
||||||
|
export const autoHistoryMode: Writable<boolean> = persist(
|
||||||
|
writable(true),
|
||||||
|
localStorage(),
|
||||||
|
'autoHistoryMode'
|
||||||
|
);
|
||||||
|
const autoHistoryStore: Writable<HistoryEntry[]> = persist(
|
||||||
|
writable([]),
|
||||||
|
localStorage(),
|
||||||
|
'autoHistoryStore'
|
||||||
|
);
|
||||||
|
const manualHistoryStore: Writable<HistoryEntry[]> = persist(
|
||||||
|
writable([]),
|
||||||
|
localStorage(),
|
||||||
|
'manualHistoryStore'
|
||||||
|
);
|
||||||
|
export const historyStore: Readable<HistoryEntry[]> = derived(
|
||||||
|
[autoHistoryMode, autoHistoryStore, manualHistoryStore],
|
||||||
|
([autoMode, autoHistories, manualHistories], set) => {
|
||||||
|
set(autoMode ? autoHistories : manualHistories);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
export const addHistoryEntry = (entry: HistoryEntry): void => {
|
||||||
|
entry.name = generateSlug(2);
|
||||||
|
|
||||||
|
if (!entry.auto) {
|
||||||
|
manualHistoryStore.update((entries) => [entry, ...entries]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
autoHistoryStore.update((entries) => {
|
||||||
|
if (entries.length === MAX_AUTO_HISTORY_LENGTH) {
|
||||||
|
entries.pop();
|
||||||
|
}
|
||||||
|
return [entry, ...entries];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const clearHistoryData = (time?: number): void => {
|
||||||
|
(get(autoHistoryMode) ? autoHistoryStore : manualHistoryStore).update((entries) =>
|
||||||
|
entries.filter((entry) => time && entry.time != time)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getPreviousState = (auto: boolean): string => {
|
||||||
|
const entries = get(auto ? autoHistoryStore : manualHistoryStore);
|
||||||
|
if (entries.length > 0) {
|
||||||
|
return JSON.stringify(entries[0].state);
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
};
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { version } from 'mermaid/package.json';
|
||||||
|
interface Link {
|
||||||
|
title: string;
|
||||||
|
href: string;
|
||||||
|
icon?: string;
|
||||||
|
}
|
||||||
|
const links: Link[] = [
|
||||||
|
{
|
||||||
|
title: 'Documentation',
|
||||||
|
href: 'https://mermaid-js.github.io/mermaid/#/n00b-gettingStarted'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Tutorial',
|
||||||
|
href: 'https://github.com/mermaid-js/mermaid/blob/develop/docs/Tutorials.md'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Mermaid',
|
||||||
|
href: 'https://github.com/mermaid-js/mermaid'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'CLI',
|
||||||
|
href: 'https://github.com/mermaid-js/mermaid-cli'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '',
|
||||||
|
href: 'https://github.com/mermaid-js/mermaid-live-editor',
|
||||||
|
icon: 'fab fa-github fa-lg'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<header class="p-2 bg-indigo-400 text-white font-bold flex flex-wrap items-center">
|
||||||
|
<div class="flex-1 flex justify-between items-center">
|
||||||
|
<a href="/">Mermaid<span class="text-xs font-thin">v{version}</span> Live Editor</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<label for="menu-toggle" class="pointer-cursor lg:hidden block"
|
||||||
|
><svg
|
||||||
|
class="fill-current text-gray-900"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
><title>menu</title><path d="M0 3h20v2H0V3zm0 6h20v2H0V9zm0 6h20v2H0v-2z" /></svg
|
||||||
|
></label>
|
||||||
|
<input class="hidden" type="checkbox" id="menu-toggle" />
|
||||||
|
|
||||||
|
<div class="hidden lg:flex lg:items-center lg:w-auto w-full" id="menu">
|
||||||
|
<nav>
|
||||||
|
<ul class="lg:flex items-center justify-between text-base pt-4 lg:pt-0">
|
||||||
|
{#each links as { title, href, icon }}
|
||||||
|
<li>
|
||||||
|
<a class="nav-btn" target="_blank" {href}>
|
||||||
|
{#if icon}
|
||||||
|
<i class={icon} />
|
||||||
|
{/if}
|
||||||
|
{title}</a>
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<style lang="postcss">
|
||||||
|
#menu-toggle:checked + #menu {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.nav-btn {
|
||||||
|
@apply lg:p-2 py-3 px-0 block border-b-2 border-transparent hover:border-white;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { updateCode } from '$lib/util/state';
|
||||||
|
import Card from '$lib/components/card/card.svelte';
|
||||||
|
|
||||||
|
const samples = {
|
||||||
|
'Flow Chart': `graph TD
|
||||||
|
A[Christmas] -->|Get money| B(Go shopping)
|
||||||
|
B --> C{Let me think}
|
||||||
|
C -->|One| D[Laptop]
|
||||||
|
C -->|Two| E[iPhone]
|
||||||
|
C -->|Three| F[fa:fa-car Car]`,
|
||||||
|
'Sequence Diagram': `sequenceDiagram
|
||||||
|
Alice->>+John: Hello John, how are you?
|
||||||
|
Alice->>+John: John, can you hear me?
|
||||||
|
John-->>-Alice: Hi Alice, I can hear you!
|
||||||
|
John-->>-Alice: I feel great!
|
||||||
|
`,
|
||||||
|
'Class Diagram': `classDiagram
|
||||||
|
Animal <|-- Duck
|
||||||
|
Animal <|-- Fish
|
||||||
|
Animal <|-- Zebra
|
||||||
|
Animal : +int age
|
||||||
|
Animal : +String gender
|
||||||
|
Animal: +isMammal()
|
||||||
|
Animal: +mate()
|
||||||
|
class Duck{
|
||||||
|
+String beakColor
|
||||||
|
+swim()
|
||||||
|
+quack()
|
||||||
|
}
|
||||||
|
class Fish{
|
||||||
|
-int sizeInFeet
|
||||||
|
-canEat()
|
||||||
|
}
|
||||||
|
class Zebra{
|
||||||
|
+bool is_wild
|
||||||
|
+run()
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
'State Diagram': `stateDiagram-v2
|
||||||
|
[*] --> Still
|
||||||
|
Still --> [*]
|
||||||
|
Still --> Moving
|
||||||
|
Moving --> Still
|
||||||
|
Moving --> Crash
|
||||||
|
Crash --> [*]
|
||||||
|
`,
|
||||||
|
'Gantt Chart': `gantt
|
||||||
|
title A Gantt Diagram
|
||||||
|
dateFormat YYYY-MM-DD
|
||||||
|
section Section
|
||||||
|
A task :a1, 2014-01-01, 30d
|
||||||
|
Another task :after a1 , 20d
|
||||||
|
section Another
|
||||||
|
Task in sec :2014-01-12 , 12d
|
||||||
|
another task : 24d
|
||||||
|
`,
|
||||||
|
'Pie Chart': `pie title Pets adopted by volunteers
|
||||||
|
"Dogs" : 386
|
||||||
|
"Cats" : 85
|
||||||
|
"Rats" : 15
|
||||||
|
`,
|
||||||
|
'ER Diagram': `erDiagram
|
||||||
|
CUSTOMER }|..|{ DELIVERY-ADDRESS : has
|
||||||
|
CUSTOMER ||--o{ ORDER : places
|
||||||
|
CUSTOMER ||--o{ INVOICE : "liable for"
|
||||||
|
DELIVERY-ADDRESS ||--o{ ORDER : receives
|
||||||
|
INVOICE ||--|{ ORDER : covers
|
||||||
|
ORDER ||--|{ ORDER-ITEM : includes
|
||||||
|
PRODUCT-CATEGORY ||--|{ PRODUCT : contains
|
||||||
|
PRODUCT ||--o{ ORDER-ITEM : "ordered in"
|
||||||
|
`,
|
||||||
|
'Git Graph': `gitGraph:
|
||||||
|
options
|
||||||
|
{
|
||||||
|
"nodeSpacing": 150,
|
||||||
|
"nodeRadius": 10
|
||||||
|
}
|
||||||
|
end
|
||||||
|
commit
|
||||||
|
branch newbranch
|
||||||
|
checkout newbranch
|
||||||
|
commit
|
||||||
|
commit
|
||||||
|
checkout master
|
||||||
|
commit
|
||||||
|
commit
|
||||||
|
merge newbranch
|
||||||
|
|
||||||
|
`,
|
||||||
|
'User Journey': ` journey
|
||||||
|
title My working day
|
||||||
|
section Go to work
|
||||||
|
Make tea: 5: Me
|
||||||
|
Go upstairs: 3: Me
|
||||||
|
Do work: 1: Me, Cat
|
||||||
|
section Go home
|
||||||
|
Go downstairs: 5: Me
|
||||||
|
Sit down: 3: Me
|
||||||
|
`
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadSampleDiagram = (diagramType: string): void => {
|
||||||
|
updateCode(samples[diagramType], true, true);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Card title="Presets" isOpen={false}>
|
||||||
|
<div class="flex gap-2 flex-wrap p-2">
|
||||||
|
{#each Object.keys(samples) as sample}
|
||||||
|
<button
|
||||||
|
class="rounded p-2 bg-indigo-400 shadow flex-auto text-white hover:bg-indigo-500"
|
||||||
|
on:click={() => loadSampleDiagram(sample)}>{sample}</button>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { errorStore } from '$lib/util/error';
|
||||||
|
|
||||||
|
import { codeStore } from '$lib/util/state';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import type { Mermaid } from 'mermaid';
|
||||||
|
|
||||||
|
const mermaid: Mermaid = (window.mermaid as unknown) as Mermaid;
|
||||||
|
let code: string = '';
|
||||||
|
let container: HTMLDivElement;
|
||||||
|
let error: boolean = false;
|
||||||
|
let outOfSync: boolean = false;
|
||||||
|
let manualUpdate: boolean = true;
|
||||||
|
onMount(async () => {
|
||||||
|
codeStore.subscribe((state) => {
|
||||||
|
try {
|
||||||
|
if (container && state && (state.updateDiagram || state.autoSync)) {
|
||||||
|
if (!state.autoSync) {
|
||||||
|
$codeStore.updateDiagram = false;
|
||||||
|
}
|
||||||
|
outOfSync = false;
|
||||||
|
manualUpdate = true;
|
||||||
|
// Replacing special characters '<' and '>' with encoded '<' and '>'
|
||||||
|
code = state.code; //.replace(/</g, '<').replace(/>/g, '>');
|
||||||
|
const scroll = container.parentElement.parentElement.parentElement.scrollTop;
|
||||||
|
container.innerHTML = code;
|
||||||
|
delete container.dataset.processed;
|
||||||
|
mermaid.initialize(Object.assign({}, JSON.parse(state.mermaid)));
|
||||||
|
mermaid.init(container);
|
||||||
|
mermaid.render('graph-div', code, insertSvg);
|
||||||
|
container.parentElement.parentElement.parentElement.scrollTop = scroll;
|
||||||
|
} else if (manualUpdate) {
|
||||||
|
manualUpdate = false;
|
||||||
|
} else {
|
||||||
|
outOfSync = true;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log('view fail', e);
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
errorStore.subscribe((err) => {
|
||||||
|
if (typeof err === 'undefined') {
|
||||||
|
error = false;
|
||||||
|
} else {
|
||||||
|
error = true;
|
||||||
|
console.log('Error: ', err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
const insertSvg = (svgCode, bindFunctions) => {};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div id="view" class="p-2" class:error class:outOfSync>
|
||||||
|
<div id="container" bind:this={container} class="flex-1 overflow-auto" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#view {
|
||||||
|
border: 1px solor darkred;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.error,
|
||||||
|
.outOfSync {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
// this action (https://svelte.dev/tutorial/actions) allows us to
|
||||||
|
// progressively enhance a <form> that already works without JS
|
||||||
|
export function enhance(
|
||||||
|
form: HTMLFormElement,
|
||||||
|
{
|
||||||
|
pending,
|
||||||
|
error,
|
||||||
|
result
|
||||||
|
}: {
|
||||||
|
pending?: (data: FormData, form: HTMLFormElement) => void;
|
||||||
|
error?: (res: Response, error: Error, form: HTMLFormElement) => void;
|
||||||
|
result: (res: Response, form: HTMLFormElement) => void;
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
let current_token: {};
|
||||||
|
|
||||||
|
async function handle_submit(e: Event) {
|
||||||
|
const token = (current_token = {});
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const body = new FormData(form);
|
||||||
|
|
||||||
|
if (pending) pending(body, form);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await fetch(form.action, {
|
||||||
|
method: form.method,
|
||||||
|
headers: {
|
||||||
|
accept: 'application/json'
|
||||||
|
},
|
||||||
|
body
|
||||||
|
});
|
||||||
|
|
||||||
|
if (token !== current_token) return;
|
||||||
|
|
||||||
|
if (res.ok) {
|
||||||
|
result(res, form);
|
||||||
|
} else if (error) {
|
||||||
|
error(res, null, form);
|
||||||
|
} else {
|
||||||
|
console.error(await res.text());
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (error) {
|
||||||
|
error(null, e, form);
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
form.addEventListener('submit', handle_submit);
|
||||||
|
|
||||||
|
return {
|
||||||
|
destroy() {
|
||||||
|
form.removeEventListener('submit', handle_submit);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
Vendored
+7
@@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* Can be made globally available by placing this
|
||||||
|
* inside `global.d.ts` and removing `export` keyword
|
||||||
|
*/
|
||||||
|
export interface Locals {
|
||||||
|
userid: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import { writable } from 'svelte/store';
|
||||||
|
|
||||||
|
export const errorStore = writable(undefined);
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
export const notify = (message: string): void => {
|
||||||
|
alert(message);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const prompt = (message: string): boolean => {
|
||||||
|
return confirm(message);
|
||||||
|
};
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
import { writable, get, derived } from 'svelte/store';
|
||||||
|
import { toBase64, fromBase64 } from 'js-base64';
|
||||||
|
import { persist, localStorage } from '@macfja/svelte-persistent-store';
|
||||||
|
|
||||||
|
const defaultState: State = {
|
||||||
|
code: `graph TD
|
||||||
|
A[Christmas] -->|Get money| B(Go shopping)
|
||||||
|
B --> C{Let me think}
|
||||||
|
C -->|One| D[Laptop]
|
||||||
|
C -->|Two| E[iPhone]
|
||||||
|
C -->|Three| F[fa:fa-car Car]
|
||||||
|
`,
|
||||||
|
mermaid: JSON.stringify(
|
||||||
|
{
|
||||||
|
theme: 'default'
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
2
|
||||||
|
),
|
||||||
|
updateEditor: false,
|
||||||
|
autoSync: true,
|
||||||
|
updateDiagram: true
|
||||||
|
};
|
||||||
|
|
||||||
|
export const codeStore = persist(writable(defaultState), localStorage(), 'codeStore');
|
||||||
|
export const base64State = derived([codeStore], ([code], set) => {
|
||||||
|
set(toBase64(JSON.stringify(code), true));
|
||||||
|
});
|
||||||
|
|
||||||
|
export const loadState = (data: string): void => {
|
||||||
|
let state: State;
|
||||||
|
try {
|
||||||
|
const stateStr = fromBase64(data);
|
||||||
|
console.log(`Tring to load state: ${stateStr}`);
|
||||||
|
state = JSON.parse(stateStr);
|
||||||
|
} catch (e) {
|
||||||
|
if (data) {
|
||||||
|
console.error('Init error', e);
|
||||||
|
}
|
||||||
|
state = get(codeStore);
|
||||||
|
console.log(state);
|
||||||
|
}
|
||||||
|
updateCodeStore({ ...state, updateEditor: true });
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateCodeStore = (newState: State): void => {
|
||||||
|
codeStore.update((state) => {
|
||||||
|
return { ...state, ...newState };
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
let prompted = false;
|
||||||
|
export const updateCode = (code: string, updateEditor: boolean, updateDiagram = false): void => {
|
||||||
|
const lines = (code.match(/\n/g) || '').length + 1;
|
||||||
|
|
||||||
|
if (lines > 50 && !prompted && get(codeStore).autoSync) {
|
||||||
|
const turnOff = confirm(
|
||||||
|
'Long diagram deteced. Turn off Auto Sync? Click the sync logo to manually sync.'
|
||||||
|
);
|
||||||
|
prompted = true;
|
||||||
|
if (turnOff) {
|
||||||
|
updateCodeStore({
|
||||||
|
autoSync: false
|
||||||
|
} as State);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
codeStore.update((state) => {
|
||||||
|
return { ...state, code, updateEditor, updateDiagram };
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateConfig = (config: string, updateEditor: boolean): void => {
|
||||||
|
codeStore.update((state) => {
|
||||||
|
return { ...state, mermaid: config, updateEditor };
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const initURLSubscription = (): void => {
|
||||||
|
base64State.subscribe((state: string) => {
|
||||||
|
window.location.hash = state;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getStateString = (): string => {
|
||||||
|
return JSON.stringify(get(codeStore));
|
||||||
|
};
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { initURLSubscription, loadState, updateCodeStore } from './state';
|
||||||
|
|
||||||
|
export const loadStateFromURL = (): void => {
|
||||||
|
loadState(window.location.hash.slice(1));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const syncDiagram = (): void => {
|
||||||
|
updateCodeStore({
|
||||||
|
updateDiagram: true
|
||||||
|
} as State);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const initHandler = (): void => {
|
||||||
|
loadStateFromURL();
|
||||||
|
syncDiagram();
|
||||||
|
initURLSubscription();
|
||||||
|
};
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import '../app.postcss';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<main class="h-screen">
|
||||||
|
<slot />
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
<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 { 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',
|
||||||
|
icon: 'fas fa-code'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'config',
|
||||||
|
title: 'Config',
|
||||||
|
icon: 'fas fa-cogs'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
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 hidden md: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-4 mx-2"
|
||||||
|
title="Sync Diagram"
|
||||||
|
on:click={syncDiagram}><i class="fas fa-sync" /></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"
|
||||||
|
title="View diagram in new page"
|
||||||
|
on:click|stopPropagation={() => viewDiagram()}><i class="far fa-eye" /> View</button>
|
||||||
|
|
||||||
|
<div class="flex-1 overflow-auto">
|
||||||
|
<View />
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
<div class="flex md:hidden bg-white rounded shadow p-2 mx-2">
|
||||||
|
Code editing not supported on mobile. Please use a desktop browser
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { goto } from '$app/navigation';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import { base } from '$app/paths';
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
// Handle old live editor links and redirect to new version
|
||||||
|
const hash = window.location.hash.split('/');
|
||||||
|
let newURL = 'edit';
|
||||||
|
if (hash.length > 2) {
|
||||||
|
newURL = `${hash[1]}#${hash[2]}`;
|
||||||
|
}
|
||||||
|
await goto(`${base}/${newURL}`, {
|
||||||
|
replaceState: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<title>Mermaid Live Editor</title>
|
||||||
|
</svelte:head>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import View from '$lib/components/view.svelte';
|
||||||
|
import { initHandler } from '$lib/util/util';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
onMount(initHandler);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<View />
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
@@ -0,0 +1,3 @@
|
|||||||
|
# https://www.robotstxt.org/robotstxt.html
|
||||||
|
User-agent: *
|
||||||
|
Disallow:
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import preprocess from 'svelte-preprocess';
|
||||||
|
import adapter from '@sveltejs/adapter-static';
|
||||||
|
|
||||||
|
/** @type {import('@sveltejs/kit').Config} */
|
||||||
|
const config = {
|
||||||
|
// Consult https://github.com/sveltejs/svelte-preprocess
|
||||||
|
// for more information about preprocessors
|
||||||
|
preprocess: [
|
||||||
|
preprocess({
|
||||||
|
postcss: true
|
||||||
|
})
|
||||||
|
],
|
||||||
|
|
||||||
|
kit: {
|
||||||
|
adapter: adapter({
|
||||||
|
pages: 'docs'
|
||||||
|
}),
|
||||||
|
paths: process.env['CI']
|
||||||
|
? {
|
||||||
|
base: '/mermaid-svelte-kit'
|
||||||
|
}
|
||||||
|
: {},
|
||||||
|
ssr: false,
|
||||||
|
// hydrate the <div id="svelte"> element in src/app.html
|
||||||
|
target: '#svelte'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
const { tailwindExtractor } = require('tailwindcss/lib/lib/purgeUnusedStyles');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
mode: 'aot',
|
||||||
|
purge: {
|
||||||
|
content: ['./src/**/*.{html,js,svelte,ts}'],
|
||||||
|
options: {
|
||||||
|
defaultExtractor: (content) => [
|
||||||
|
// If this stops working, please open an issue at https://github.com/svelte-add/tailwindcss/issues rather than bothering Tailwind Labs about it
|
||||||
|
...tailwindExtractor(content),
|
||||||
|
// Match Svelte class: directives (https://github.com/tailwindlabs/tailwindcss/discussions/1731)
|
||||||
|
...[...content.matchAll(/(?:class:)*([\w\d-/:%.]+)/gm)].map(
|
||||||
|
([_match, group, ..._rest]) => group
|
||||||
|
)
|
||||||
|
]
|
||||||
|
},
|
||||||
|
safelist: [/^svelte-[\d\w]+$/]
|
||||||
|
},
|
||||||
|
theme: {
|
||||||
|
extend: {}
|
||||||
|
},
|
||||||
|
variants: {
|
||||||
|
extend: {}
|
||||||
|
},
|
||||||
|
plugins: [require('@tailwindcss/forms')]
|
||||||
|
};
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"module": "es2020",
|
||||||
|
"lib": ["es2020", "ESNext"],
|
||||||
|
"target": "es2019",
|
||||||
|
/**
|
||||||
|
svelte-preprocess cannot figure out whether you have a value or a type, so tell TypeScript
|
||||||
|
to enforce using \`import type\` instead of \`import\` for Types.
|
||||||
|
*/
|
||||||
|
"importsNotUsedAsValues": "error",
|
||||||
|
"isolatedModules": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
/**
|
||||||
|
To have warnings/errors of the Svelte compiler at the correct position,
|
||||||
|
enable source maps by default.
|
||||||
|
*/
|
||||||
|
"sourceMap": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"baseUrl": ".",
|
||||||
|
"allowJs": true,
|
||||||
|
"checkJs": true,
|
||||||
|
"paths": {
|
||||||
|
"$lib/*": ["src/lib/*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.ts", "src/**/*.svelte"]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user