+14
-1
@@ -5,6 +5,7 @@ module.exports = {
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
// 'plugin:@typescript-eslint/recommended-requiring-type-checking',
|
||||
'plugin:@typescript-eslint/strict',
|
||||
'prettier'
|
||||
],
|
||||
plugins: ['svelte3', 'tailwindcss', '@typescript-eslint', 'es', 'vitest'],
|
||||
@@ -19,7 +20,19 @@ module.exports = {
|
||||
'package.json',
|
||||
'tsconfig.json'
|
||||
],
|
||||
overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }],
|
||||
overrides: [
|
||||
{ files: ['*.svelte'], processor: 'svelte3/svelte3' },
|
||||
{
|
||||
files: ['*.ts'],
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:@typescript-eslint/recommended-requiring-type-checking',
|
||||
'plugin:@typescript-eslint/strict',
|
||||
'prettier'
|
||||
]
|
||||
}
|
||||
],
|
||||
settings: {
|
||||
'svelte3/typescript': () => require('typescript')
|
||||
},
|
||||
|
||||
@@ -8,7 +8,7 @@ jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v5
|
||||
- uses: actions/stale@v6
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
exempt-issue-labels: 'retained'
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"editor.formatOnSave": true,
|
||||
"cSpell.words": ["asyncable", "mindmap", "pako", "Serde", "serdes"],
|
||||
"cSpell.words": ["asyncable", "KROKI", "mindmap", "pako", "Serde", "serdes", "tailwindcss"],
|
||||
"vitest.commandLine": "yarn test:unit",
|
||||
"vitest.enable": true,
|
||||
"testing.autoRun.mode": "rerun",
|
||||
|
||||
@@ -17,6 +17,7 @@ export const verifyFileSize = (
|
||||
) => {
|
||||
const fileName = `mermaid-${fileType}-2022-01-01-000000.${extension}`;
|
||||
const filePath = `${downloadsFolder}/${fileName}`;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
cy.verifyDownload(fileName);
|
||||
cy.readFile(filePath, null, {
|
||||
log: false
|
||||
@@ -31,6 +32,7 @@ export const verifyFileSnapshot = (
|
||||
) => {
|
||||
const fileName = `mermaid-${fileType}-2022-01-01-000000.${extension}`;
|
||||
const filePath = `${downloadsFolder}/${fileName}`;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
cy.verifyDownload(fileName);
|
||||
cy.readFile(filePath, null, {
|
||||
log: false
|
||||
|
||||
+9
-9
@@ -29,15 +29,15 @@
|
||||
"@testing-library/svelte": "3.2.2",
|
||||
"@types/pako": "2.0.0",
|
||||
"@types/uuid": "8.3.4",
|
||||
"@typescript-eslint/eslint-plugin": "5.42.0",
|
||||
"@typescript-eslint/parser": "5.42.0",
|
||||
"@vitest/ui": "0.24.3",
|
||||
"@typescript-eslint/eslint-plugin": "5.43.0",
|
||||
"@typescript-eslint/parser": "5.43.0",
|
||||
"@vitest/ui": "0.25.1",
|
||||
"autoprefixer": "10.4.12",
|
||||
"c8": "7.12.0",
|
||||
"chai": "4.3.6",
|
||||
"cssnano": "5.1.13",
|
||||
"cy-verify-downloads": "0.1.11",
|
||||
"cypress": "10.11.0",
|
||||
"cypress": "11.0.1",
|
||||
"cypress-localstorage-commands": "2.2.1",
|
||||
"eslint": "8.27.0",
|
||||
"eslint-config-prettier": "8.5.0",
|
||||
@@ -45,7 +45,7 @@
|
||||
"eslint-plugin-es": "4.1.0",
|
||||
"eslint-plugin-postcss-modules": "2.0.0",
|
||||
"eslint-plugin-svelte3": "4.0.0",
|
||||
"eslint-plugin-tailwindcss": "3.6.2",
|
||||
"eslint-plugin-tailwindcss": "3.7.0",
|
||||
"eslint-plugin-vitest": "0.0.11",
|
||||
"esserializer": "1.3.2",
|
||||
"husky": "8.0.1",
|
||||
@@ -56,25 +56,25 @@
|
||||
"postcss-load-config": "4.0.1",
|
||||
"prettier": "2.7.1",
|
||||
"prettier-plugin-svelte": "2.8.0",
|
||||
"svelte": "3.52.0",
|
||||
"svelte": "3.53.1",
|
||||
"svelte-preprocess": "4.10.7",
|
||||
"tailwindcss": "3.2.1",
|
||||
"tslib": "2.4.0",
|
||||
"typescript": "4.8.4",
|
||||
"vite": "3.2.2",
|
||||
"vitest": "0.24.3"
|
||||
"vitest": "0.25.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@mermaid-js/mermaid-mindmap": "9.2.2",
|
||||
"analytics": "0.8.1",
|
||||
"analytics-plugin-plausible": "0.0.6",
|
||||
"daisyui": "2.38.1",
|
||||
"daisyui": "2.40.1",
|
||||
"js-base64": "3.7.2",
|
||||
"mermaid": "9.2.2",
|
||||
"moment": "2.29.4",
|
||||
"monaco-editor": "0.34.1",
|
||||
"monaco-mermaid": "1.0.6",
|
||||
"pako": "2.0.4",
|
||||
"pako": "2.1.0",
|
||||
"random-word-slugs": "0.1.6",
|
||||
"svg-pan-zoom": "3.6.1",
|
||||
"uuid": "9.0.0"
|
||||
|
||||
Vendored
+5
-5
@@ -1,11 +1,11 @@
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
interface ImportMetaEnv {
|
||||
readonly MERMAID_RENDERER_URL: string;
|
||||
readonly MERMAID_KROKI_RENDERER_URL: string;
|
||||
readonly MERMAID_CDN_URL: string;
|
||||
readonly MERMAID_BASE_URL: string;
|
||||
readonly MERMAID_LOCAL: boolean;
|
||||
readonly MERMAID_RENDERER_URL?: string;
|
||||
readonly MERMAID_KROKI_RENDERER_URL?: string;
|
||||
readonly MERMAID_CDN_URL?: string;
|
||||
readonly MERMAID_BASE_URL?: string;
|
||||
readonly MERMAID_LOCAL?: boolean;
|
||||
// more env variables...
|
||||
}
|
||||
|
||||
|
||||
Vendored
+2
-1
@@ -9,7 +9,8 @@ declare global {
|
||||
namespace jest {
|
||||
interface Matchers<R = void>
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
// @ts-expect-error
|
||||
// eslint-disable-next-line no-undef
|
||||
extends TestingLibraryMatchers<typeof expect.stringContaining, R> {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { browser } from '$app/environment';
|
||||
import Card from '$lib/components/card/card.svelte';
|
||||
import Card from '$lib/components/Card/Card.svelte';
|
||||
import { env } from '$lib/util/env';
|
||||
import { pakoSerde } from '$lib/util/serde';
|
||||
import { stateStore } from '$lib/util/state';
|
||||
@@ -15,8 +15,8 @@
|
||||
`mermaid-diagram-${moment().format('YYYY-MM-DD-HHmmss')}.${ext}`;
|
||||
|
||||
const getBase64SVG = (svg?: HTMLElement, width?: number, height?: number): string => {
|
||||
svg?.setAttribute('height', `${height}px`);
|
||||
svg?.setAttribute('width', `${width}px`); // Workaround https://stackoverflow.com/questions/28690643/firefox-error-rendering-an-svg-image-to-html5-canvas-with-drawimage
|
||||
height && svg?.setAttribute('height', `${height}px`);
|
||||
width && svg?.setAttribute('width', `${width}px`); // Workaround https://stackoverflow.com/questions/28690643/firefox-error-rendering-an-svg-image-to-html5-canvas-with-drawimage
|
||||
if (!svg) {
|
||||
svg = getSvgEl();
|
||||
}
|
||||
@@ -28,7 +28,10 @@
|
||||
|
||||
const exportImage = (event: Event, exporter: Exporter) => {
|
||||
const canvas: HTMLCanvasElement = document.createElement('canvas');
|
||||
const svg: HTMLElement = document.querySelector('#container svg');
|
||||
const svg: HTMLElement | null = document.querySelector('#container svg');
|
||||
if (!svg) {
|
||||
throw new Error('svg not found');
|
||||
}
|
||||
const box: DOMRect = svg.getBoundingClientRect();
|
||||
canvas.width = box.width;
|
||||
canvas.height = box.height;
|
||||
@@ -43,6 +46,9 @@
|
||||
}
|
||||
|
||||
const context = canvas.getContext('2d');
|
||||
if (!context) {
|
||||
throw new Error('context not found');
|
||||
}
|
||||
context.fillStyle = 'white';
|
||||
context.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
@@ -56,12 +62,12 @@
|
||||
|
||||
const getSvgEl = () => {
|
||||
const svgEl: HTMLElement = document
|
||||
.querySelector('#container svg')
|
||||
.querySelector('#container svg')!
|
||||
.cloneNode(true) as HTMLElement;
|
||||
svgEl.setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
|
||||
const fontAwesomeCdnUrl = Array.from(document.head.getElementsByTagName('link'))
|
||||
.map((l) => l.href)
|
||||
.find((h) => h && h.includes('font-awesome'));
|
||||
.find((h) => h.includes('font-awesome'));
|
||||
if (fontAwesomeCdnUrl == null) {
|
||||
return svgEl;
|
||||
}
|
||||
@@ -99,10 +105,10 @@
|
||||
context.drawImage(image, 0, 0, canvas.width, canvas.height);
|
||||
canvas.toBlob((blob) => {
|
||||
try {
|
||||
// @ts-ignore: https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1004/files
|
||||
if (!blob) {
|
||||
throw new Error('blob is empty');
|
||||
}
|
||||
void navigator.clipboard.write([
|
||||
/* eslint-disable no-undef */
|
||||
// @ts-ignore: https://github.com/microsoft/TypeScript/issues/43821
|
||||
new ClipboardItem({
|
||||
[blob.type]: blob
|
||||
})
|
||||
@@ -142,7 +148,7 @@
|
||||
let gistURL = '';
|
||||
stateStore.subscribe(({ loader }) => {
|
||||
if (loader?.type === 'gist') {
|
||||
// @ts-ignore Gist will have url
|
||||
// @ts-expect-error Gist will have url
|
||||
gistURL = loader.config.url;
|
||||
}
|
||||
});
|
||||
@@ -166,8 +172,7 @@
|
||||
if (browser && ['mermaid.live', 'netlify'].some((path) => window.location.host.includes(path))) {
|
||||
isNetlify = true;
|
||||
}
|
||||
stateStore.subscribe(async (state) => {
|
||||
const { code, serialized } = await state;
|
||||
stateStore.subscribe(({ code, serialized }) => {
|
||||
iUrl = `${rendererUrl}/img/${serialized}?type=png`;
|
||||
svgUrl = `${rendererUrl}/svg/${serialized}`;
|
||||
krokiUrl = `${krokiRendererUrl}/mermaid/svg/${pakoSerde.serialize(code)}`;
|
||||
@@ -1,11 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { Tab } from '$lib/types';
|
||||
import { slide } from 'svelte/transition';
|
||||
import Tabs from './tabs.svelte';
|
||||
import Tabs from './Tabs.svelte';
|
||||
export let isCloseable = true;
|
||||
export let isOpen = true;
|
||||
export let tabs: Tab[] = [];
|
||||
export let activeTabID: string = '';
|
||||
export let activeTabID = '';
|
||||
export let title: string;
|
||||
$: isOpen = isCloseable ? isOpen : true;
|
||||
$: isTabsShown = isOpen && tabs.length > 0;
|
||||
@@ -0,0 +1,3 @@
|
||||
// Vitest Snapshot v1
|
||||
|
||||
exports[`card.svelte > mounts 1`] = `"<div><div class=\\"card rounded overflow-hidden m-2 flex-grow flex flex-col shadow-2xl\\"><div class=\\"bg-primary p-2 pb-0 flex-none cursor-pointer\\"><div class=\\"flex justify-between\\"><div class=\\"flex cursor-default s-lTROw8sJayZ1\\"><span class=\\"mr-2 font-semibold s-lTROw8sJayZ1\\"><i class=\\"fas fa-chevron-right icon s-lTROw8sJayZ1 isOpen\\"></i> TabTest</span> <ul class=\\"tabs s-lTROw8sJayZ1\\"><div class=\\"tab tab-lifted tab-active s-lTROw8sJayZ1\\"><i class=\\"mr-1 fab fa-git-alt s-lTROw8sJayZ1\\"></i> title1 </div><div class=\\"tab tab-lifted text-primary-content s-lTROw8sJayZ1\\"><i class=\\"mr-1 far fa-bookmark s-lTROw8sJayZ1\\"></i> title2 </div></ul></div><!--<Tabs>--> <div class=\\"flex gap-x-4 items-center -mt-2\\"></div></div></div> <div class=\\"card-body p-0 flex-grow overflow-auto text-base-content\\"></div></div><!--<Card>--></div>"`;
|
||||
@@ -1,6 +1,6 @@
|
||||
import { cleanup, render } from '@testing-library/svelte';
|
||||
import { describe, expect, it, afterEach } from 'vitest';
|
||||
import Card from './card.svelte';
|
||||
import Card from './Card.svelte';
|
||||
|
||||
describe('card.svelte', () => {
|
||||
// TODO: @testing-library/svelte claims to add this automatically but it doesn't work without explicit afterEach
|
||||
@@ -10,8 +10,8 @@ describe('card.svelte', () => {
|
||||
const { container } = render(Card, {
|
||||
title: 'TabTest',
|
||||
tabs: [
|
||||
{ id: 't1', title: 'title1' },
|
||||
{ id: 't2', title: 'title2' }
|
||||
{ id: 't1', title: 'title1', icon: 'fab fa-git-alt' },
|
||||
{ id: 't2', title: 'title2', icon: 'far fa-bookmark' }
|
||||
]
|
||||
});
|
||||
expect(container).toBeTruthy();
|
||||
@@ -8,9 +8,9 @@
|
||||
import initEditor from 'monaco-mermaid';
|
||||
import { logEvent } from '$lib/util/stats';
|
||||
|
||||
let divEl: HTMLDivElement = null;
|
||||
let editor: monaco.editor.IStandaloneCodeEditor;
|
||||
let Monaco: typeof monaco;
|
||||
let divEl: HTMLDivElement | undefined = undefined;
|
||||
let editor: monaco.editor.IStandaloneCodeEditor | undefined;
|
||||
let Monaco: typeof monaco | undefined;
|
||||
let editorOptions: monaco.editor.IStandaloneEditorConstructionOptions = {
|
||||
minimap: {
|
||||
enabled: false
|
||||
@@ -22,7 +22,9 @@
|
||||
|
||||
stateStore.subscribe(({ errorMarkers, editorMode, code, mermaid }) => {
|
||||
console.log('editor store subscription', { code, mermaid });
|
||||
if (!editor) return;
|
||||
if (!editor || !Monaco) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update editor text if it's different
|
||||
const newText = editorMode === 'code' ? code : mermaid;
|
||||
@@ -34,12 +36,17 @@
|
||||
|
||||
// Update editor mode if it's different
|
||||
const language = editorMode === 'code' ? 'mermaid' : 'json';
|
||||
if (editor.getModel().getLanguageId() !== language) {
|
||||
Monaco?.editor.setModelLanguage(editor.getModel(), language);
|
||||
const model = editor.getModel();
|
||||
if (!model) {
|
||||
console.error("editor model doesn't exist");
|
||||
return;
|
||||
}
|
||||
if (model.getLanguageId() !== language) {
|
||||
Monaco.editor.setModelLanguage(model, language);
|
||||
}
|
||||
|
||||
// Display/clear errors
|
||||
Monaco?.editor.setModelMarkers(editor.getModel(), 'mermaid', errorMarkers);
|
||||
Monaco.editor.setModelMarkers(model, 'mermaid', errorMarkers);
|
||||
});
|
||||
|
||||
themeStore.subscribe(({ isDark }) => {
|
||||
@@ -60,7 +67,7 @@
|
||||
// errorDebug();
|
||||
let i = 0;
|
||||
while (i++ < 500) {
|
||||
// @ts-ignore : This is a hack to handle a svelte-kit error when importing monaco.
|
||||
// @ts-expect-error : This is a hack to handle a svelte-kit error when importing monaco.
|
||||
Monaco = window.monaco;
|
||||
if (Monaco !== undefined) {
|
||||
return;
|
||||
@@ -72,13 +79,20 @@
|
||||
|
||||
onMount(async () => {
|
||||
await loadMonaco(); // Fix https://github.com/mermaid-js/mermaid-live-editor/issues/175
|
||||
if (!Monaco) {
|
||||
throw new Error('Monaco failed to load');
|
||||
}
|
||||
if (!divEl) {
|
||||
throw new Error('divEl is undefined');
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
initEditor(Monaco);
|
||||
errorDebug(100);
|
||||
editor = Monaco.editor.create(divEl, editorOptions);
|
||||
editor.onDidChangeModelContent(({ isFlush, changes }) => {
|
||||
const newText = editor.getValue();
|
||||
const newText = editor?.getValue();
|
||||
console.log('editor onDidChangeModelContent', { text, newText, isFlush, changes });
|
||||
if (text === newText || isFlush) {
|
||||
if (!newText || text === newText || isFlush) {
|
||||
return;
|
||||
}
|
||||
text = newText;
|
||||
@@ -95,19 +109,21 @@
|
||||
});
|
||||
}
|
||||
});
|
||||
Monaco?.editor.setTheme($themeStore.isDark ? 'mermaid-dark' : 'mermaid');
|
||||
Monaco.editor.setTheme($themeStore.isDark ? 'mermaid-dark' : 'mermaid');
|
||||
const resizeObserver = new ResizeObserver((entries) => {
|
||||
editor.layout({
|
||||
editor!.layout({
|
||||
height: entries[0].contentRect.height,
|
||||
width: entries[0].contentRect.width
|
||||
});
|
||||
});
|
||||
|
||||
resizeObserver.observe(divEl.parentElement);
|
||||
if (divEl.parentElement) {
|
||||
resizeObserver.observe(divEl.parentElement);
|
||||
}
|
||||
console.log(`editor mounted`);
|
||||
return () => {
|
||||
console.log(`editor disposed`);
|
||||
editor.dispose();
|
||||
editor?.dispose();
|
||||
};
|
||||
});
|
||||
</script>
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import Card from '$lib/components/card/card.svelte';
|
||||
import Card from '$lib/components/Card/Card.svelte';
|
||||
import { inputStateStore, getStateString } from '$lib/util/state';
|
||||
import {
|
||||
addHistoryEntry,
|
||||
@@ -14,7 +14,7 @@
|
||||
import { onMount } from 'svelte';
|
||||
import { get } from 'svelte/store';
|
||||
import moment from 'moment';
|
||||
import type { HistoryType, State, Tab } from '$lib/types';
|
||||
import type { HistoryEntry, HistoryType, State, Tab } from '$lib/types';
|
||||
import { logEvent } from '$lib/util/stats';
|
||||
|
||||
const HISTORY_SAVE_INTERVAL = 60000;
|
||||
@@ -60,7 +60,7 @@
|
||||
}
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
const data = JSON.parse(e.target.result as string);
|
||||
const data: HistoryEntry[] = JSON.parse(e.target.result as string);
|
||||
restoreHistory(data);
|
||||
};
|
||||
reader.readAsText(file);
|
||||
+19
-13
@@ -7,7 +7,7 @@ import {
|
||||
historyModeStore,
|
||||
historyStore
|
||||
} from './history';
|
||||
import { defaultState } from '../../util/state';
|
||||
import { defaultState } from '$lib/util/state';
|
||||
import { get } from 'svelte/store';
|
||||
|
||||
describe('history', () => {
|
||||
@@ -21,9 +21,9 @@ describe('history', () => {
|
||||
type: 'manual'
|
||||
});
|
||||
|
||||
const [manualEntry]: HistoryEntry[] = JSON.parse(
|
||||
window.localStorage.getItem('manualHistoryStore')
|
||||
);
|
||||
const [manualEntry] = JSON.parse(
|
||||
window.localStorage.getItem('manualHistoryStore') ?? '[]'
|
||||
) as HistoryEntry[];
|
||||
|
||||
expect(manualEntry.time).toBe(12345);
|
||||
expect(manualEntry.type).toBe('manual');
|
||||
@@ -36,7 +36,9 @@ describe('history', () => {
|
||||
type: 'auto'
|
||||
});
|
||||
|
||||
const [autoEntry]: HistoryEntry[] = JSON.parse(window.localStorage.getItem('autoHistoryStore'));
|
||||
const [autoEntry] = JSON.parse(
|
||||
window.localStorage.getItem('autoHistoryStore') ?? '[]'
|
||||
) as HistoryEntry[];
|
||||
|
||||
expect(autoEntry.time).toBe(54321);
|
||||
expect(autoEntry.type).toBe('auto');
|
||||
@@ -101,19 +103,23 @@ describe('history migration', () => {
|
||||
'autoHistoryStore',
|
||||
'[{"state":{"code":"graph TD\\n A[New Year] -->|Get money| B(Go shopping)","mermaid":"{\\n \\"theme\\": \\"dark\\"\\n}","autoSync":true,"updateDiagram":false},"time":0,"type":"auto","name":"barking-dog"},{"state":{"code":"graph TD\\n A[Christmas] -->|Get money| B(Go shopping)","mermaid":"{\\n \\"theme\\": \\"dark\\"\\n}","autoSync":true,"updateDiagram":true},"time":0,"type":"manual","name":"needy-mosquito"}]'
|
||||
);
|
||||
let manualHistoryStore: HistoryEntry[] = JSON.parse(
|
||||
window.localStorage.getItem('manualHistoryStore')
|
||||
);
|
||||
let autoHistoryStore: HistoryEntry[] = JSON.parse(
|
||||
window.localStorage.getItem('autoHistoryStore')
|
||||
);
|
||||
let manualHistoryStore = JSON.parse(
|
||||
window.localStorage.getItem('manualHistoryStore') ?? '[]'
|
||||
) as HistoryEntry[];
|
||||
let autoHistoryStore = JSON.parse(
|
||||
window.localStorage.getItem('autoHistoryStore') ?? '[]'
|
||||
) as HistoryEntry[];
|
||||
expect(manualHistoryStore.every(({ id }) => id !== undefined)).toBe(false);
|
||||
expect(autoHistoryStore.every(({ id }) => id !== undefined)).toBe(false);
|
||||
|
||||
injectHistoryIDs();
|
||||
|
||||
manualHistoryStore = JSON.parse(window.localStorage.getItem('manualHistoryStore'));
|
||||
autoHistoryStore = JSON.parse(window.localStorage.getItem('autoHistoryStore'));
|
||||
manualHistoryStore = JSON.parse(
|
||||
window.localStorage.getItem('manualHistoryStore') ?? '[]'
|
||||
) as HistoryEntry[];
|
||||
autoHistoryStore = JSON.parse(
|
||||
window.localStorage.getItem('autoHistoryStore') ?? '[]'
|
||||
) as HistoryEntry[];
|
||||
expect(manualHistoryStore.every(({ id }) => id !== undefined)).toBe(true);
|
||||
expect(autoHistoryStore.every(({ id }) => id !== undefined)).toBe(true);
|
||||
});
|
||||
@@ -1,13 +1,13 @@
|
||||
<script context="module">
|
||||
<script context="module" lang="ts">
|
||||
import { version } from 'mermaid/package.json';
|
||||
import { analytics } from '$lib/util/stats';
|
||||
analytics?.track('version', {
|
||||
void analytics?.track('version', {
|
||||
mermaidVersion: version
|
||||
});
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import Theme from './theme.svelte';
|
||||
import Theme from './Theme.svelte';
|
||||
|
||||
interface Link {
|
||||
title: string;
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { updateCode } from '$lib/util/state';
|
||||
import Card from '$lib/components/card/card.svelte';
|
||||
import Card from '$lib/components/Card/Card.svelte';
|
||||
import { logEvent } from '$lib/util/stats';
|
||||
|
||||
const samples = {
|
||||
@@ -104,7 +104,8 @@
|
||||
Mermaid`
|
||||
};
|
||||
|
||||
const loadSampleDiagram = (diagramType: string): void => {
|
||||
type SampleTypes = keyof typeof samples;
|
||||
const loadSampleDiagram = (diagramType: SampleTypes): void => {
|
||||
updateCode(samples[diagramType], {
|
||||
updateDiagram: true,
|
||||
resetPanZoom: true
|
||||
@@ -113,8 +114,8 @@
|
||||
};
|
||||
|
||||
// Adding in this array will add an icon to the preset menu
|
||||
const newDiagrams: Array<keyof typeof samples> = ['Mindmap'];
|
||||
const diagramOrder: Array<keyof typeof samples> = [
|
||||
const newDiagrams: SampleTypes[] = ['Mindmap'];
|
||||
const diagramOrder: SampleTypes[] = [
|
||||
'Sequence',
|
||||
'Flow',
|
||||
'Class',
|
||||
@@ -1,4 +1,4 @@
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import { setTheme, themeStore } from '$lib/util/theme';
|
||||
|
||||
const themes = [
|
||||
@@ -52,7 +52,7 @@
|
||||
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
|
||||
<ul tabindex="0" class="p-4 menu compact">
|
||||
{#each themes as theme}
|
||||
<li class={theme.includes($themeStore.theme) ? 'bordered' : ''}>
|
||||
<li class:bordered={$themeStore.theme !== undefined && theme.includes($themeStore.theme)}>
|
||||
<span
|
||||
class="btn btn-ghost justify-start"
|
||||
on:click={() => setTheme(theme)}
|
||||
@@ -6,6 +6,7 @@
|
||||
import { logEvent } from '$lib/util/stats';
|
||||
import { AsyncQueue, cmdKey } from '$lib/util/util';
|
||||
import { render as renderDiagram } from '$lib/util/mermaid';
|
||||
import type { MermaidConfig } from 'mermaid';
|
||||
|
||||
let code = '';
|
||||
let config = '';
|
||||
@@ -16,9 +17,12 @@
|
||||
let hide = false;
|
||||
let manualUpdate = true;
|
||||
let panZoomEnabled = $stateStore.panZoom;
|
||||
let pzoom: SvgPanZoom.Instance;
|
||||
let pzoom: typeof panzoom | undefined;
|
||||
|
||||
const handlePanZoomChange = () => {
|
||||
if (!pzoom) {
|
||||
return;
|
||||
}
|
||||
const pan = pzoom.getPan();
|
||||
const zoom = pzoom.getZoom();
|
||||
updateCodeStore({ pan, zoom });
|
||||
@@ -32,8 +36,11 @@
|
||||
hide = true;
|
||||
pzoom?.destroy();
|
||||
pzoom = undefined;
|
||||
Promise.resolve().then(() => {
|
||||
void Promise.resolve().then(() => {
|
||||
const graphDiv = document.getElementById('graph-div');
|
||||
if (!graphDiv) {
|
||||
return;
|
||||
}
|
||||
pzoom = panzoom(graphDiv, {
|
||||
onPan: handlePanZoomChange,
|
||||
onZoom: handlePanZoomChange,
|
||||
@@ -70,10 +77,10 @@
|
||||
code = state.code;
|
||||
config = state.mermaid;
|
||||
panZoomEnabled = state.panZoom;
|
||||
const scroll = view.parentElement.scrollTop;
|
||||
const scroll = view.parentElement!.scrollTop;
|
||||
delete container.dataset.processed;
|
||||
await renderDiagram(
|
||||
Object.assign({}, JSON.parse(state.mermaid)),
|
||||
Object.assign({}, JSON.parse(state.mermaid)) as MermaidConfig,
|
||||
code,
|
||||
'graph-div',
|
||||
(svgCode, bindFunctions) => {
|
||||
@@ -82,6 +89,9 @@
|
||||
container.innerHTML = svgCode;
|
||||
// console.log(container.innerHTML);
|
||||
const graphDiv = document.getElementById('graph-div');
|
||||
if (!graphDiv) {
|
||||
throw new Error('graph-div not found');
|
||||
}
|
||||
graphDiv.setAttribute('height', '100%');
|
||||
graphDiv.style.maxWidth = '100%';
|
||||
if (bindFunctions) {
|
||||
@@ -90,7 +100,7 @@
|
||||
}
|
||||
}
|
||||
);
|
||||
view.parentElement.scrollTop = scroll;
|
||||
view.parentElement!.scrollTop = scroll;
|
||||
error = false;
|
||||
} else if (manualUpdate) {
|
||||
manualUpdate = false;
|
||||
@@ -106,8 +116,8 @@
|
||||
const q = new AsyncQueue(handleStateChange);
|
||||
|
||||
onMount(() => {
|
||||
stateStore.subscribe(async (state) => {
|
||||
await q.process(state);
|
||||
stateStore.subscribe((state) => {
|
||||
void q.process(state);
|
||||
});
|
||||
window.addEventListener('resize', () => {
|
||||
if ($stateStore.panZoom && pzoom) {
|
||||
@@ -1,3 +0,0 @@
|
||||
// Vitest Snapshot v1
|
||||
|
||||
exports[`card.svelte > mounts 1`] = `"<div><div class=\\"card rounded overflow-hidden m-2 flex-grow flex flex-col shadow-2xl\\"><div class=\\"bg-primary p-2 pb-0 flex-none cursor-pointer\\"><div class=\\"flex justify-between\\"><div class=\\"flex cursor-default s-_wx1E_JHsCoF\\"><span class=\\"mr-2 font-semibold s-_wx1E_JHsCoF\\"><i class=\\"fas fa-chevron-right icon s-_wx1E_JHsCoF isOpen\\"></i> TabTest</span> <ul class=\\"tabs s-_wx1E_JHsCoF\\"><div class=\\"tab tab-lifted tab-active s-_wx1E_JHsCoF\\"><i class=\\"mr-1 undefined s-_wx1E_JHsCoF\\"></i> title1 </div><div class=\\"tab tab-lifted text-primary-content s-_wx1E_JHsCoF\\"><i class=\\"mr-1 undefined s-_wx1E_JHsCoF\\"></i> title2 </div></ul></div><!--<Tabs>--> <div class=\\"flex gap-x-4 items-center -mt-2\\"></div></div></div> <div class=\\"card-body p-0 flex-grow overflow-auto text-base-content\\"></div></div><!--<Card>--></div>"`;
|
||||
Vendored
+14
-4
@@ -73,14 +73,24 @@ export type HistoryEntry = { id: string; state: State; time: number; url?: strin
|
||||
}
|
||||
);
|
||||
|
||||
export interface DocConfig {
|
||||
[key: string]: {
|
||||
export type DocConfig = Record<
|
||||
string,
|
||||
{
|
||||
code: string;
|
||||
config?: string;
|
||||
};
|
||||
}
|
||||
}
|
||||
>;
|
||||
|
||||
export type EditorMode = 'code' | 'config';
|
||||
|
||||
export type Loader = (url: string) => Promise<State>;
|
||||
export type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>;
|
||||
|
||||
export interface ErrorHash {
|
||||
loc: {
|
||||
first_line: number;
|
||||
last_line: number;
|
||||
first_column: number;
|
||||
last_column: number;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,17 +3,23 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import type { State } from '$lib/types';
|
||||
import { defaultState } from '../state';
|
||||
import { addHistoryEntry } from '../../components/history/history';
|
||||
import { defaultState } from '$lib/util/state';
|
||||
import { addHistoryEntry } from '$lib/components/History/history';
|
||||
|
||||
const codeFileName = 'code.mmd';
|
||||
const configFileName = 'config.json';
|
||||
|
||||
interface GithubFile {
|
||||
truncated: boolean;
|
||||
raw_url: string;
|
||||
content: string;
|
||||
}
|
||||
|
||||
const isValidGist = (files: any): boolean => {
|
||||
return codeFileName in files;
|
||||
};
|
||||
|
||||
const getFileContent = async (file: any): Promise<string> => {
|
||||
const getFileContent = async (file: GithubFile): Promise<string> => {
|
||||
if (file.truncated) {
|
||||
return await (await fetch(file.raw_url)).text();
|
||||
}
|
||||
@@ -29,16 +35,26 @@ interface GistData {
|
||||
url: string;
|
||||
}
|
||||
|
||||
interface GistResponse {
|
||||
files: Record<string, GithubFile>;
|
||||
html_url: string;
|
||||
history: { url: string; committed_at: string; version: string; user: { login: string } }[];
|
||||
}
|
||||
|
||||
const getGistData = async (gistURL: string): Promise<GistData> => {
|
||||
const path = gistURL.split('github.com').pop();
|
||||
if (!path) {
|
||||
throw new Error('Invalid GitHub URL' + gistURL);
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [_, __, gistID, revisionID] = gistURL.split('github.com').pop().split('/');
|
||||
const [_, __, gistID, revisionID] = path.split('/');
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
const { html_url, files, history } = await (
|
||||
const { html_url, files, history }: GistResponse = await (
|
||||
await fetch(`https://api.github.com/gists/${gistID}${revisionID ? '/' + revisionID : ''}`)
|
||||
).json();
|
||||
if (isValidGist(files)) {
|
||||
const code = await getFileContent(files[codeFileName]);
|
||||
let config: string;
|
||||
let config = '{}';
|
||||
if (configFileName in files) {
|
||||
config = await getFileContent(files[configFileName]);
|
||||
}
|
||||
@@ -50,10 +66,10 @@ const getGistData = async (gistURL: string): Promise<GistData> => {
|
||||
config,
|
||||
author: currentItem.user.login,
|
||||
time: new Date(currentItem.committed_at).getTime(),
|
||||
version: (currentItem.version as string).slice(-7)
|
||||
version: currentItem.version.slice(-7)
|
||||
};
|
||||
} else {
|
||||
throw 'Invalid gist provided';
|
||||
throw new Error('Invalid gist provided');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -73,35 +89,38 @@ const getStateFromGist = (gist: GistData, gistURL: string = gist.url): State =>
|
||||
};
|
||||
|
||||
export const loadGistData = async (gistURL: string): Promise<State> => {
|
||||
try {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [_, __, gistID, revisionID] = gistURL.split('github.com').pop().split('/');
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
const { history } = await (
|
||||
await fetch(`https://api.github.com/gists/${gistID}${revisionID ? '/' + revisionID : ''}`)
|
||||
).json();
|
||||
const gistHistory: GistData[] = [];
|
||||
for (const entry of history) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
const data: GistData = await getGistData(entry.url).catch(() => undefined);
|
||||
data && gistHistory.push(data);
|
||||
}
|
||||
if (gistHistory.length === 0) {
|
||||
throw 'Invalid gist provided';
|
||||
}
|
||||
gistHistory.reverse();
|
||||
const state = getStateFromGist(gistHistory.slice(-1).pop(), gistURL);
|
||||
for (const gist of gistHistory) {
|
||||
addHistoryEntry({
|
||||
state: getStateFromGist(gist),
|
||||
time: gist.time,
|
||||
type: 'loader',
|
||||
url: gist.url,
|
||||
name: `${gist.author} v${gist.version}`
|
||||
});
|
||||
}
|
||||
return state;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
const path = gistURL.split('github.com').pop();
|
||||
if (!path) {
|
||||
throw new Error('Invalid GitHub URL' + gistURL);
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [_, __, gistID, revisionID] = path.split('/');
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
const { history }: GistResponse = await (
|
||||
await fetch(`https://api.github.com/gists/${gistID}${revisionID ? '/' + revisionID : ''}`)
|
||||
).json();
|
||||
const gistHistory: GistData[] = [];
|
||||
for (const entry of history) {
|
||||
const data: GistData | undefined = await getGistData(entry.url).catch(() => undefined);
|
||||
data && gistHistory.push(data);
|
||||
}
|
||||
if (gistHistory.length === 0) {
|
||||
throw new Error('Invalid gist provided');
|
||||
}
|
||||
gistHistory.reverse();
|
||||
const entry = gistHistory.slice(-1).pop();
|
||||
if (!entry) {
|
||||
throw new Error('Invalid gist provided');
|
||||
}
|
||||
const state = getStateFromGist(entry, gistURL);
|
||||
for (const gist of gistHistory) {
|
||||
addHistoryEntry({
|
||||
state: getStateFromGist(gist),
|
||||
time: gist.time,
|
||||
type: 'loader',
|
||||
url: gist.url,
|
||||
name: `${gist.author} v${gist.version}`
|
||||
});
|
||||
}
|
||||
return state;
|
||||
};
|
||||
|
||||
@@ -8,10 +8,11 @@ const loaders: Record<string, Loader> = {
|
||||
export const loadDataFromUrl = async (): Promise<void> => {
|
||||
const searchParams = new URLSearchParams(window.location.search);
|
||||
let state: Partial<State> = defaultState;
|
||||
let code: string, config: string;
|
||||
let code: string | undefined = undefined;
|
||||
let config: string | undefined = undefined;
|
||||
let loaded = false;
|
||||
const codeURL: string = searchParams.get('code');
|
||||
const configURL: string = searchParams.get('config');
|
||||
const codeURL: string | undefined = searchParams.get('code') ?? undefined;
|
||||
const configURL: string | undefined = searchParams.get('config') ?? undefined;
|
||||
|
||||
if (codeURL) {
|
||||
code = await (await fetch(codeURL)).text();
|
||||
@@ -23,9 +24,6 @@ export const loadDataFromUrl = async (): Promise<void> => {
|
||||
config = defaultState.mermaid;
|
||||
}
|
||||
if (!code) {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
for (const [key, value] of searchParams.entries()) {
|
||||
if (key in loaders) {
|
||||
try {
|
||||
@@ -38,6 +36,9 @@ export const loadDataFromUrl = async (): Promise<void> => {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!codeURL) {
|
||||
throw new Error('Code URL is not defined');
|
||||
}
|
||||
state = {
|
||||
code,
|
||||
mermaid: config,
|
||||
|
||||
@@ -23,5 +23,5 @@ export const render = async (
|
||||
|
||||
export const parse = async (code: string): Promise<boolean> => {
|
||||
await init();
|
||||
return (await mermaid.parseAsync(code)) as boolean;
|
||||
return await mermaid.parseAsync(code);
|
||||
};
|
||||
|
||||
@@ -16,18 +16,22 @@ describe('migrations', () => {
|
||||
it('should migrate from v0 to v1', async () => {
|
||||
const { applyMigrations } = await import('./migrations');
|
||||
let manualHistoryStore: HistoryEntry[] = JSON.parse(
|
||||
window.localStorage.getItem('manualHistoryStore')
|
||||
);
|
||||
window.localStorage.getItem('manualHistoryStore') ?? '[]'
|
||||
) as HistoryEntry[];
|
||||
let autoHistoryStore: HistoryEntry[] = JSON.parse(
|
||||
window.localStorage.getItem('autoHistoryStore')
|
||||
);
|
||||
window.localStorage.getItem('autoHistoryStore') ?? '[]'
|
||||
) as HistoryEntry[];
|
||||
expect(manualHistoryStore.every(({ id }) => id !== undefined)).toBe(false);
|
||||
expect(autoHistoryStore.every(({ id }) => id !== undefined)).toBe(false);
|
||||
|
||||
applyMigrations();
|
||||
|
||||
manualHistoryStore = JSON.parse(window.localStorage.getItem('manualHistoryStore'));
|
||||
autoHistoryStore = JSON.parse(window.localStorage.getItem('autoHistoryStore'));
|
||||
manualHistoryStore = JSON.parse(
|
||||
window.localStorage.getItem('manualHistoryStore') ?? '[]'
|
||||
) as HistoryEntry[];
|
||||
autoHistoryStore = JSON.parse(
|
||||
window.localStorage.getItem('autoHistoryStore') ?? '[]'
|
||||
) as HistoryEntry[];
|
||||
expect(manualHistoryStore.every(({ id }) => id !== undefined)).toBe(true);
|
||||
expect(autoHistoryStore.every(({ id }) => id !== undefined)).toBe(true);
|
||||
});
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { writable, get, type Writable } from 'svelte/store';
|
||||
import { persist, localStorage } from '$lib/util/persist';
|
||||
import { injectHistoryIDs } from '$lib/components/history/history';
|
||||
import { injectHistoryIDs } from '$lib/components/History/history';
|
||||
import { logEvent } from './stats';
|
||||
|
||||
interface MigrationState {
|
||||
version: number;
|
||||
}
|
||||
|
||||
const migrations: { [key: string]: () => void } = {
|
||||
const migrations: Record<string, () => void> = {
|
||||
injectHistoryIDs
|
||||
};
|
||||
|
||||
|
||||
+16
-22
@@ -39,16 +39,16 @@ let noWarnings = false;
|
||||
/**
|
||||
* List of storages where the warning have already been displayed.
|
||||
*/
|
||||
const alreadyWarnFor: Array<string> = [];
|
||||
const alreadyWarnFor: string[] = [];
|
||||
|
||||
/**
|
||||
* Add a log to indicate that the requested Storage have not been found.
|
||||
* @param {string} storageName
|
||||
*/
|
||||
const warnStorageNotFound = (storageName) => {
|
||||
const isProduction = typeof process !== 'undefined' && process.env?.NODE_ENV === 'production';
|
||||
const warnStorageNotFound = (storageName: string) => {
|
||||
const isProduction = typeof process !== 'undefined' && process.env.NODE_ENV === 'production';
|
||||
|
||||
if (!noWarnings && alreadyWarnFor.indexOf(storageName) === -1 && !isProduction) {
|
||||
if (!noWarnings && !alreadyWarnFor.includes(storageName) && !isProduction) {
|
||||
let message = `Unable to find the ${storageName}. No data will be persisted.`;
|
||||
if (typeof window === 'undefined') {
|
||||
message +=
|
||||
@@ -60,17 +60,8 @@ const warnStorageNotFound = (storageName) => {
|
||||
}
|
||||
};
|
||||
|
||||
const allowedClasses = [];
|
||||
/**
|
||||
* Add a class to the allowed list of classes to be serialized
|
||||
* @param classDef The class to add to the list
|
||||
*/
|
||||
export const addSerializableClass = (classDef: () => unknown): void => {
|
||||
allowedClasses.push(classDef);
|
||||
};
|
||||
|
||||
const serialize = (value: unknown): string => ESSerializer.serialize(value);
|
||||
const deserialize = (value: string): unknown => {
|
||||
const deserialize = (value?: string | null): unknown => {
|
||||
// @TODO: to remove in the next major
|
||||
if (value === 'undefined') {
|
||||
return undefined;
|
||||
@@ -78,7 +69,7 @@ const deserialize = (value: string): unknown => {
|
||||
|
||||
if (value !== null && value !== undefined) {
|
||||
try {
|
||||
return ESSerializer.deserialize(value, allowedClasses);
|
||||
return ESSerializer.deserialize(value);
|
||||
} catch (e) {
|
||||
// Do nothing
|
||||
// use the value "as is"
|
||||
@@ -162,7 +153,7 @@ export function persist<T>(
|
||||
store.set(initialValue);
|
||||
}
|
||||
|
||||
if ((storage as SelfUpdateStorageInterface<T>).addListener) {
|
||||
if ('addListener' in storage) {
|
||||
(storage as SelfUpdateStorageInterface<T>).addListener(key, (newValue) => {
|
||||
store.set(newValue);
|
||||
});
|
||||
@@ -184,7 +175,7 @@ function getBrowserStorage(
|
||||
browserStorage: Storage,
|
||||
listenExternalChanges = false
|
||||
): SelfUpdateStorageInterface<any> {
|
||||
const listeners: Array<{ key: string; listener: (newValue: any) => void }> = [];
|
||||
const listeners: { key: string; listener: (newValue: any) => void }[] = [];
|
||||
const listenerFunction = (event: StorageEvent) => {
|
||||
const eventKey = event.key;
|
||||
if (event.storageArea === browserStorage) {
|
||||
@@ -196,12 +187,14 @@ function getBrowserStorage(
|
||||
}
|
||||
};
|
||||
const connect = () => {
|
||||
if (listenExternalChanges && typeof window !== 'undefined' && window?.addEventListener) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
if (listenExternalChanges && typeof window !== 'undefined' && window.addEventListener) {
|
||||
window.addEventListener('storage', listenerFunction);
|
||||
}
|
||||
};
|
||||
const disconnect = () => {
|
||||
if (listenExternalChanges && typeof window !== 'undefined' && window?.removeEventListener) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
if (listenExternalChanges && typeof window !== 'undefined' && window.removeEventListener) {
|
||||
window.removeEventListener('storage', listenerFunction);
|
||||
}
|
||||
};
|
||||
@@ -237,10 +230,11 @@ function getBrowserStorage(
|
||||
|
||||
/**
|
||||
* Storage implementation that use the browser local storage
|
||||
* @param {boolean} listenExternalChanges - Update the store if the localStorage is updated from another page
|
||||
* @param listenExternalChanges - Update the store if the localStorage is updated from another page
|
||||
*/
|
||||
export function localStorage<T>(listenExternalChanges = false): StorageInterface<T> {
|
||||
if (typeof window !== 'undefined' && window?.localStorage) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
if (typeof window !== 'undefined' && window.localStorage) {
|
||||
return getBrowserStorage(window.localStorage, listenExternalChanges);
|
||||
}
|
||||
warnStorageNotFound('window.localStorage');
|
||||
@@ -250,7 +244,7 @@ export function localStorage<T>(listenExternalChanges = false): StorageInterface
|
||||
/**
|
||||
* Storage implementation that do nothing
|
||||
*/
|
||||
export function noopStorage(): StorageInterface<any> {
|
||||
export function noopStorage<T>(): StorageInterface<T> {
|
||||
return {
|
||||
getValue(): null {
|
||||
return null;
|
||||
|
||||
@@ -36,7 +36,7 @@ const serdes: { [key in SerdeType]: Serde } = {
|
||||
};
|
||||
|
||||
export const serializeState = (state: State, serde: SerdeType = 'pako'): string => {
|
||||
if (serdes[serde] === undefined) {
|
||||
if (!(serde in serdes)) {
|
||||
throw new Error(`Unknown serde type: ${serde}`);
|
||||
}
|
||||
const json = JSON.stringify(state);
|
||||
|
||||
+21
-12
@@ -5,7 +5,9 @@ import { serializeState, deserializeState } from './serde';
|
||||
import { cmdKey, errorDebug, AsyncQueue } from './util';
|
||||
import { parse } from './mermaid';
|
||||
|
||||
import type { MarkerData, State, ValidatedState } from '$lib/types';
|
||||
import type { ErrorHash, MarkerData, State, ValidatedState } from '$lib/types';
|
||||
import type { MermaidConfig } from 'mermaid';
|
||||
|
||||
export const defaultState: State = {
|
||||
code: `graph TD
|
||||
A[Christmas] -->|Get money| B(Go shopping)
|
||||
@@ -50,7 +52,7 @@ export const currentState: ValidatedState = (() => {
|
||||
};
|
||||
})();
|
||||
|
||||
let q: AsyncQueue<State>;
|
||||
let q: AsyncQueue<State> | undefined;
|
||||
|
||||
const processState = async (state: State) => {
|
||||
const processed: ValidatedState = {
|
||||
@@ -69,14 +71,19 @@ const processState = async (state: State) => {
|
||||
processed.error = e;
|
||||
errorDebug();
|
||||
console.error(e);
|
||||
if (e.hash) {
|
||||
if ('hash' in e) {
|
||||
const {
|
||||
loc: { first_line, last_line, first_column, last_column }
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
} = e.hash as ErrorHash;
|
||||
try {
|
||||
const marker: MarkerData = {
|
||||
severity: 8, // Error
|
||||
startLineNumber: e.hash.loc.first_line,
|
||||
startColumn: e.hash.loc.first_column,
|
||||
endLineNumber: e.hash.loc.last_line,
|
||||
endColumn: (e.hash.loc.last_column as number) + 1,
|
||||
startLineNumber: first_line,
|
||||
startColumn: first_column,
|
||||
endLineNumber: last_line,
|
||||
endColumn: last_column + 1,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment
|
||||
message: e.str
|
||||
};
|
||||
processed.errorMarkers = [marker];
|
||||
@@ -99,7 +106,7 @@ export const stateStore: Readable<ValidatedState> = derived(
|
||||
set(newState);
|
||||
});
|
||||
}
|
||||
q.process(state);
|
||||
void q.process(state);
|
||||
},
|
||||
currentState
|
||||
);
|
||||
@@ -109,8 +116,10 @@ export const loadState = (data: string): void => {
|
||||
console.log(`Loading '${data}'`);
|
||||
try {
|
||||
state = deserializeState(data);
|
||||
const mermaidConfig: { [key: string]: string } =
|
||||
typeof state.mermaid === 'string' ? JSON.parse(state.mermaid) : state.mermaid;
|
||||
const mermaidConfig: MermaidConfig =
|
||||
typeof state.mermaid === 'string'
|
||||
? (JSON.parse(state.mermaid) as MermaidConfig)
|
||||
: state.mermaid;
|
||||
if (
|
||||
mermaidConfig.securityLevel &&
|
||||
mermaidConfig.securityLevel !== 'strict' &&
|
||||
@@ -180,7 +189,7 @@ export const updateConfig = (config: string): void => {
|
||||
|
||||
export const toggleDarkTheme = (dark: boolean): void => {
|
||||
inputStateStore.update((state) => {
|
||||
const config = JSON.parse(state.mermaid);
|
||||
const config = JSON.parse(state.mermaid) as MermaidConfig;
|
||||
if (!config.theme || ['dark', 'default'].includes(config.theme)) {
|
||||
config.theme = dark ? 'dark' : 'default';
|
||||
}
|
||||
@@ -194,7 +203,7 @@ export const initURLSubscription = (): void => {
|
||||
stateStore.subscribe(({ serialized }) => {
|
||||
clearTimeout(urlDebounce);
|
||||
urlDebounce = window.setTimeout(() => {
|
||||
history.replaceState(undefined, undefined, `#${serialized}`);
|
||||
history.replaceState(undefined, '', `#${serialized}`);
|
||||
}, 250);
|
||||
});
|
||||
};
|
||||
|
||||
+10
-9
@@ -1,6 +1,6 @@
|
||||
import { browser } from '$app/environment';
|
||||
import type { AnalyticsInstance } from 'analytics';
|
||||
export let analytics: AnalyticsInstance;
|
||||
export let analytics: AnalyticsInstance | undefined;
|
||||
|
||||
export const initAnalytics = async (): Promise<void> => {
|
||||
if (browser && !analytics) {
|
||||
@@ -27,7 +27,7 @@ export const initAnalytics = async (): Promise<void> => {
|
||||
}
|
||||
};
|
||||
|
||||
export const detectType = (text: string): string => {
|
||||
export const detectType = (text: string): string | undefined => {
|
||||
const possibleDiagramTypes = [
|
||||
'classDiagram',
|
||||
'erDiagram',
|
||||
@@ -49,7 +49,7 @@ export const detectType = (text: string): string => {
|
||||
};
|
||||
|
||||
export const countLines = (code: string): number => {
|
||||
return (code.match(/\n/g) || '').length + 1;
|
||||
return (code.match(/\n/g)?.length ?? 0) + 1;
|
||||
};
|
||||
|
||||
export const saveStatistics = (graph: string): void => {
|
||||
@@ -80,19 +80,20 @@ const delaysPerEvent = {
|
||||
themeChange: defaultDelay
|
||||
};
|
||||
export type AnalyticsEvent = keyof typeof delaysPerEvent;
|
||||
const timeouts: Record<string, number> = {};
|
||||
const timeouts: Map<string, number> = new Map<string, number>();
|
||||
// manual debounce to reduce the number of events sent to analytics
|
||||
export const logEvent = (name: AnalyticsEvent, data?: unknown): void => {
|
||||
if (!analytics) {
|
||||
return;
|
||||
}
|
||||
const key = data ? JSON.stringify({ name, data }) : name;
|
||||
if (timeouts[key] === undefined) {
|
||||
if (!timeouts.has(key)) {
|
||||
void analytics.track(name, data);
|
||||
} else {
|
||||
clearTimeout(timeouts[key]);
|
||||
clearTimeout(timeouts.get(key));
|
||||
}
|
||||
timeouts[key] = window.setTimeout(() => {
|
||||
delete timeouts[key];
|
||||
}, delaysPerEvent[name]);
|
||||
timeouts.set(
|
||||
key,
|
||||
window.setTimeout(() => timeouts.delete(key), delaysPerEvent[name])
|
||||
);
|
||||
};
|
||||
|
||||
@@ -23,10 +23,10 @@ export const initHandler = async (): Promise<void> => {
|
||||
syncDiagram();
|
||||
initURLSubscription();
|
||||
await initAnalytics();
|
||||
analytics?.page();
|
||||
await analytics?.page();
|
||||
};
|
||||
|
||||
export const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
|
||||
export const isMac = navigator.platform.toUpperCase().includes('MAC');
|
||||
export const cmdKey = isMac ? 'Cmd' : 'Ctrl';
|
||||
|
||||
let count = 0;
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
// This can be removed once https://github.com/sveltejs/kit/issues/1612 is fixed.
|
||||
// Then move it into src and vite will bundle it automatically.
|
||||
onMount(() => {
|
||||
window.addEventListener('hashchange', async (ev) => {
|
||||
await initHandler();
|
||||
window.addEventListener('hashchange', () => {
|
||||
void initHandler();
|
||||
});
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<script lang="ts">
|
||||
import Editor from '$lib/components/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 Editor from '$lib/components/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 { inputStateStore, stateStore, updateCodeStore } from '$lib/util/state';
|
||||
import { cmdKey, initHandler, syncDiagram } from '$lib/util/util';
|
||||
import { onMount } from 'svelte';
|
||||
@@ -86,6 +86,10 @@
|
||||
await initHandler();
|
||||
const resizer = document.getElementById('resizeHandler');
|
||||
const element = document.getElementById('editorPane');
|
||||
if (!resizer || !element) {
|
||||
console.debug('Failed to find resize handler or editor pane', { resizer, element });
|
||||
return;
|
||||
}
|
||||
const resize = (e: { pageX: number }) => {
|
||||
const newWidth = e.pageX - element.getBoundingClientRect().left;
|
||||
if (newWidth > 50) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import View from '$lib/components/view.svelte';
|
||||
import View from '$lib/components/View.svelte';
|
||||
import { initHandler } from '$lib/util/util';
|
||||
import { onMount } from 'svelte';
|
||||
onMount(initHandler);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"compilerOptions": {
|
||||
"resolveJsonModule": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strictNullChecks": true,
|
||||
"types": ["vitest/importMeta"]
|
||||
},
|
||||
"extends": "./.svelte-kit/tsconfig.json"
|
||||
|
||||
@@ -483,14 +483,14 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@typescript-eslint/eslint-plugin@5.42.0":
|
||||
version "5.42.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.42.0.tgz#36a8c0c379870127059889a9cc7e05c260d2aaa5"
|
||||
integrity sha512-5TJh2AgL6+wpL8H/GTSjNb4WrjKoR2rqvFxR/DDTqYNk6uXn8BJMEcncLSpMbf/XV1aS0jAjYwn98uvVCiAywQ==
|
||||
"@typescript-eslint/eslint-plugin@5.43.0":
|
||||
version "5.43.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.43.0.tgz#4a5248eb31b454715ddfbf8cfbf497529a0a78bc"
|
||||
integrity sha512-wNPzG+eDR6+hhW4yobEmpR36jrqqQv1vxBq5LJO3fBAktjkvekfr4BRl+3Fn1CM/A+s8/EiGUbOMDoYqWdbtXA==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "5.42.0"
|
||||
"@typescript-eslint/type-utils" "5.42.0"
|
||||
"@typescript-eslint/utils" "5.42.0"
|
||||
"@typescript-eslint/scope-manager" "5.43.0"
|
||||
"@typescript-eslint/type-utils" "5.43.0"
|
||||
"@typescript-eslint/utils" "5.43.0"
|
||||
debug "^4.3.4"
|
||||
ignore "^5.2.0"
|
||||
natural-compare-lite "^1.4.0"
|
||||
@@ -498,14 +498,14 @@
|
||||
semver "^7.3.7"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/parser@5.42.0":
|
||||
version "5.42.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.42.0.tgz#be0ffbe279e1320e3d15e2ef0ad19262f59e9240"
|
||||
integrity sha512-Ixh9qrOTDRctFg3yIwrLkgf33AHyEIn6lhyf5cCfwwiGtkWhNpVKlEZApi3inGQR/barWnY7qY8FbGKBO7p3JA==
|
||||
"@typescript-eslint/parser@5.43.0":
|
||||
version "5.43.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.43.0.tgz#9c86581234b88f2ba406f0b99a274a91c11630fd"
|
||||
integrity sha512-2iHUK2Lh7PwNUlhFxxLI2haSDNyXvebBO9izhjhMoDC+S3XI9qt2DGFUsiJ89m2k7gGYch2aEpYqV5F/+nwZug==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "5.42.0"
|
||||
"@typescript-eslint/types" "5.42.0"
|
||||
"@typescript-eslint/typescript-estree" "5.42.0"
|
||||
"@typescript-eslint/scope-manager" "5.43.0"
|
||||
"@typescript-eslint/types" "5.43.0"
|
||||
"@typescript-eslint/typescript-estree" "5.43.0"
|
||||
debug "^4.3.4"
|
||||
|
||||
"@typescript-eslint/scope-manager@5.36.1":
|
||||
@@ -516,21 +516,21 @@
|
||||
"@typescript-eslint/types" "5.36.1"
|
||||
"@typescript-eslint/visitor-keys" "5.36.1"
|
||||
|
||||
"@typescript-eslint/scope-manager@5.42.0":
|
||||
version "5.42.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.42.0.tgz#e1f2bb26d3b2a508421ee2e3ceea5396b192f5ef"
|
||||
integrity sha512-l5/3IBHLH0Bv04y+H+zlcLiEMEMjWGaCX6WyHE5Uk2YkSGAMlgdUPsT/ywTSKgu9D1dmmKMYgYZijObfA39Wow==
|
||||
"@typescript-eslint/scope-manager@5.43.0":
|
||||
version "5.43.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.43.0.tgz#566e46303392014d5d163704724872e1f2dd3c15"
|
||||
integrity sha512-XNWnGaqAtTJsUiZaoiGIrdJYHsUOd3BZ3Qj5zKp9w6km6HsrjPk/TGZv0qMTWyWj0+1QOqpHQ2gZOLXaGA9Ekw==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.42.0"
|
||||
"@typescript-eslint/visitor-keys" "5.42.0"
|
||||
"@typescript-eslint/types" "5.43.0"
|
||||
"@typescript-eslint/visitor-keys" "5.43.0"
|
||||
|
||||
"@typescript-eslint/type-utils@5.42.0":
|
||||
version "5.42.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.42.0.tgz#4206d7192d4fe903ddf99d09b41d4ac31b0b7dca"
|
||||
integrity sha512-HW14TXC45dFVZxnVW8rnUGnvYyRC0E/vxXShFCthcC9VhVTmjqOmtqj6H5rm9Zxv+ORxKA/1aLGD7vmlLsdlOg==
|
||||
"@typescript-eslint/type-utils@5.43.0":
|
||||
version "5.43.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.43.0.tgz#91110fb827df5161209ecca06f70d19a96030be6"
|
||||
integrity sha512-K21f+KY2/VvYggLf5Pk4tgBOPs2otTaIHy2zjclo7UZGLyFH86VfUOm5iq+OtDtxq/Zwu2I3ujDBykVW4Xtmtg==
|
||||
dependencies:
|
||||
"@typescript-eslint/typescript-estree" "5.42.0"
|
||||
"@typescript-eslint/utils" "5.42.0"
|
||||
"@typescript-eslint/typescript-estree" "5.43.0"
|
||||
"@typescript-eslint/utils" "5.43.0"
|
||||
debug "^4.3.4"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
@@ -539,10 +539,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.36.1.tgz#1cf0e28aed1cb3ee676917966eb23c2f8334ce2c"
|
||||
integrity sha512-jd93ShpsIk1KgBTx9E+hCSEuLCUFwi9V/urhjOWnOaksGZFbTOxAT47OH2d4NLJnLhkVD+wDbB48BuaycZPLBg==
|
||||
|
||||
"@typescript-eslint/types@5.42.0":
|
||||
version "5.42.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.42.0.tgz#5aeff9b5eced48f27d5b8139339bf1ef805bad7a"
|
||||
integrity sha512-t4lzO9ZOAUcHY6bXQYRuu+3SSYdD9TS8ooApZft4WARt4/f2Cj/YpvbTe8A4GuhT4bNW72goDMOy7SW71mZwGw==
|
||||
"@typescript-eslint/types@5.43.0":
|
||||
version "5.43.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.43.0.tgz#e4ddd7846fcbc074325293515fa98e844d8d2578"
|
||||
integrity sha512-jpsbcD0x6AUvV7tyOlyvon0aUsQpF8W+7TpJntfCUWU1qaIKu2K34pMwQKSzQH8ORgUrGYY6pVIh1Pi8TNeteg==
|
||||
|
||||
"@typescript-eslint/typescript-estree@5.36.1":
|
||||
version "5.36.1"
|
||||
@@ -557,29 +557,29 @@
|
||||
semver "^7.3.7"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/typescript-estree@5.42.0":
|
||||
version "5.42.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.42.0.tgz#2592d24bb5f89bf54a63384ff3494870f95b3fd8"
|
||||
integrity sha512-2O3vSq794x3kZGtV7i4SCWZWCwjEtkWfVqX4m5fbUBomOsEOyd6OAD1qU2lbvV5S8tgy/luJnOYluNyYVeOTTg==
|
||||
"@typescript-eslint/typescript-estree@5.43.0":
|
||||
version "5.43.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.43.0.tgz#b6883e58ba236a602c334be116bfc00b58b3b9f2"
|
||||
integrity sha512-BZ1WVe+QQ+igWal2tDbNg1j2HWUkAa+CVqdU79L4HP9izQY6CNhXfkNwd1SS4+sSZAP/EthI1uiCSY/+H0pROg==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.42.0"
|
||||
"@typescript-eslint/visitor-keys" "5.42.0"
|
||||
"@typescript-eslint/types" "5.43.0"
|
||||
"@typescript-eslint/visitor-keys" "5.43.0"
|
||||
debug "^4.3.4"
|
||||
globby "^11.1.0"
|
||||
is-glob "^4.0.3"
|
||||
semver "^7.3.7"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/utils@5.42.0":
|
||||
version "5.42.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.42.0.tgz#f06bd43b9a9a06ed8f29600273240e84a53f2f15"
|
||||
integrity sha512-JZ++3+h1vbeG1NUECXQZE3hg0kias9kOtcQr3+JVQ3whnjvKuMyktJAAIj6743OeNPnGBmjj7KEmiDL7qsdnCQ==
|
||||
"@typescript-eslint/utils@5.43.0":
|
||||
version "5.43.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.43.0.tgz#00fdeea07811dbdf68774a6f6eacfee17fcc669f"
|
||||
integrity sha512-8nVpA6yX0sCjf7v/NDfeaOlyaIIqL7OaIGOWSPFqUKK59Gnumd3Wa+2l8oAaYO2lk0sO+SbWFWRSvhu8gLGv4A==
|
||||
dependencies:
|
||||
"@types/json-schema" "^7.0.9"
|
||||
"@types/semver" "^7.3.12"
|
||||
"@typescript-eslint/scope-manager" "5.42.0"
|
||||
"@typescript-eslint/types" "5.42.0"
|
||||
"@typescript-eslint/typescript-estree" "5.42.0"
|
||||
"@typescript-eslint/scope-manager" "5.43.0"
|
||||
"@typescript-eslint/types" "5.43.0"
|
||||
"@typescript-eslint/typescript-estree" "5.43.0"
|
||||
eslint-scope "^5.1.1"
|
||||
eslint-utils "^3.0.0"
|
||||
semver "^7.3.7"
|
||||
@@ -604,18 +604,18 @@
|
||||
"@typescript-eslint/types" "5.36.1"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
|
||||
"@typescript-eslint/visitor-keys@5.42.0":
|
||||
version "5.42.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.42.0.tgz#ee8d62d486f41cfe646632fab790fbf0c1db5bb0"
|
||||
integrity sha512-QHbu5Hf/2lOEOwy+IUw0GoSCuAzByTAWWrOTKzTzsotiUnWFpuKnXcAhC9YztAf2EElQ0VvIK+pHJUPkM0q7jg==
|
||||
"@typescript-eslint/visitor-keys@5.43.0":
|
||||
version "5.43.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.43.0.tgz#cbbdadfdfea385310a20a962afda728ea106befa"
|
||||
integrity sha512-icl1jNH/d18OVHLfcwdL3bWUKsBeIiKYTGxMJCoGe7xFht+E4QgzOqoWYrU8XSLJWhVw8nTacbm03v23J/hFTg==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.42.0"
|
||||
"@typescript-eslint/types" "5.43.0"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
|
||||
"@vitest/ui@0.24.3":
|
||||
version "0.24.3"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/ui/-/ui-0.24.3.tgz#8058e4c9b8a276fbfef1ef0907291f19694a722b"
|
||||
integrity sha512-f5agYA/sdkiipq42TZayJoeUGjWx+opDjIVeNnb1SG2BNxqObFqh6GuJlzpGHerg4a2+ZSoVo4f4p2+dEyXPmg==
|
||||
"@vitest/ui@0.25.1":
|
||||
version "0.25.1"
|
||||
resolved "https://registry.yarnpkg.com/@vitest/ui/-/ui-0.25.1.tgz#09f55e133b2865d0751d0fd75f1bcbcbb60f7d24"
|
||||
integrity sha512-VjzyfLjNS5Zc7XCCFJW3cM2iVW305D65NG0PIWefA4A8mwOH/QJJ4nFj/4cwXzwL0/VT3/ppvpv3UDNZoh/YOQ==
|
||||
dependencies:
|
||||
sirv "^2.0.2"
|
||||
|
||||
@@ -661,7 +661,7 @@ acorn-walk@^7.0.0:
|
||||
resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz"
|
||||
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
|
||||
|
||||
acorn-walk@^8.0.2:
|
||||
acorn-walk@^8.0.2, acorn-walk@^8.2.0:
|
||||
version "8.2.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1"
|
||||
integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==
|
||||
@@ -1459,10 +1459,10 @@ cypress-localstorage-commands@2.2.1:
|
||||
resolved "https://registry.yarnpkg.com/cypress-localstorage-commands/-/cypress-localstorage-commands-2.2.1.tgz#9895d75a3e8059e78d61231c5794dc46e0fc5fdd"
|
||||
integrity sha512-m7IwoM+BMOJj7FzzN4It268c/i/Ur72CQX8JwLICkQ6ZgF1XNJOIKlQ7Rszg45ATLTjVTL1QElKCZECoU8cthQ==
|
||||
|
||||
cypress@10.11.0:
|
||||
version "10.11.0"
|
||||
resolved "https://registry.yarnpkg.com/cypress/-/cypress-10.11.0.tgz#e9fbdd7638bae3d8fb7619fd75a6330d11ebb4e8"
|
||||
integrity sha512-lsaE7dprw5DoXM00skni6W5ElVVLGAdRUUdZjX2dYsGjbY/QnpzWZ95Zom1mkGg0hAaO/QVTZoFVS7Jgr/GUPA==
|
||||
cypress@11.0.1:
|
||||
version "11.0.1"
|
||||
resolved "https://registry.yarnpkg.com/cypress/-/cypress-11.0.1.tgz#5332a1825b37ab3f4f81d74389930c55cc7cf31d"
|
||||
integrity sha512-NuEfd0Vim492RJ3m/+bbTZ3OZrqXgfAfuLaZfIQ9D5lKocS3EDr2tyAarZdAhKwLyoh7OJ33jwMeMFIDbzYqog==
|
||||
dependencies:
|
||||
"@cypress/request" "^2.88.10"
|
||||
"@cypress/xvfb" "^1.2.4"
|
||||
@@ -2039,10 +2039,10 @@ dagre@^0.8.5:
|
||||
graphlib "^2.1.8"
|
||||
lodash "^4.17.15"
|
||||
|
||||
daisyui@2.38.1:
|
||||
version "2.38.1"
|
||||
resolved "https://registry.yarnpkg.com/daisyui/-/daisyui-2.38.1.tgz#28a3303a1832f41e9804d76ec769335ac1248372"
|
||||
integrity sha512-fHAVi+bT3H9QCNM7LNEH1EMPT0IwqufuW2RNhTJZorX3TftB1bWW437BVmSt70AZH72Xvp0mVxwVS3ChSKSj0w==
|
||||
daisyui@2.40.1:
|
||||
version "2.40.1"
|
||||
resolved "https://registry.yarnpkg.com/daisyui/-/daisyui-2.40.1.tgz#26e87d3bcc25d657684a60b79099f466eb2431f7"
|
||||
integrity sha512-nzLpcU8kCLU4zoMQ0hUKw1orRRn2x/LJLZenIsHF+UlGVsml02U4u20nb/knN7B06MPpDZ4RAZyp0rEp67iwzQ==
|
||||
dependencies:
|
||||
color "^4.2"
|
||||
css-selector-tokenizer "^0.8.0"
|
||||
@@ -2558,14 +2558,14 @@ eslint-plugin-svelte3@4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-svelte3/-/eslint-plugin-svelte3-4.0.0.tgz#3d4f3dcaec5761dac8bc697f81de3613b485b4e3"
|
||||
integrity sha512-OIx9lgaNzD02+MDFNLw0GEUbuovNcglg+wnd/UY0fbZmlQSz7GlQiQ1f+yX0XvC07XPcDOnFcichqI3xCwp71g==
|
||||
|
||||
eslint-plugin-tailwindcss@3.6.2:
|
||||
version "3.6.2"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-tailwindcss/-/eslint-plugin-tailwindcss-3.6.2.tgz#56ce5722b2972ed45cb4c0bc7062d37b0cfd4995"
|
||||
integrity sha512-C9Ka3w6W9F5l/3ZDLnkdbqmeujc1vE+p5drjP1Z1UyxgoE1Nh4/f8oQ4XC45PrZsS0Nyv0YKXNH8/dn/FJZKsQ==
|
||||
eslint-plugin-tailwindcss@3.7.0:
|
||||
version "3.7.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-tailwindcss/-/eslint-plugin-tailwindcss-3.7.0.tgz#09f39b18d73141a18e7cb2431bcab89f68010b31"
|
||||
integrity sha512-e/Pe2jr0vbvNnDXylHoubDGwSh4Z5a4ZhZrkUKHU4MYdSUpjFSofGoMwBSU3d1TybTbo89ENCEWnl1BVAM1iuQ==
|
||||
dependencies:
|
||||
fast-glob "^3.2.5"
|
||||
postcss "^8.4.4"
|
||||
tailwindcss "^3.1.3"
|
||||
tailwindcss "^3.2.2"
|
||||
|
||||
eslint-plugin-vitest@0.0.11:
|
||||
version "0.0.11"
|
||||
@@ -4062,10 +4062,10 @@ p-map@^4.0.0:
|
||||
dependencies:
|
||||
aggregate-error "^3.0.0"
|
||||
|
||||
pako@2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/pako/-/pako-2.0.4.tgz#6cebc4bbb0b6c73b0d5b8d7e8476e2b2fbea576d"
|
||||
integrity sha512-v8tweI900AUkZN6heMU/4Uy4cXRc2AYNRggVmTR+dEncawDJgCdLMximOVA2p4qO57WMynangsfGRb5WD6L1Bg==
|
||||
pako@2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86"
|
||||
integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==
|
||||
|
||||
parent-module@^1.0.0:
|
||||
version "1.0.1"
|
||||
@@ -5070,10 +5070,10 @@ svelte-preprocess@4.10.7:
|
||||
sorcery "^0.10.0"
|
||||
strip-indent "^3.0.0"
|
||||
|
||||
svelte@3.52.0:
|
||||
version "3.52.0"
|
||||
resolved "https://registry.yarnpkg.com/svelte/-/svelte-3.52.0.tgz#08259eff20904c63882b66a5d409a55e8c6743b8"
|
||||
integrity sha512-FxcnEUOAVfr10vDU5dVgJN19IvqeHQCS1zfe8vayTfis9A2t5Fhx+JDe5uv/C3j//bB1umpLJ6quhgs9xyUbCQ==
|
||||
svelte@3.53.1:
|
||||
version "3.53.1"
|
||||
resolved "https://registry.yarnpkg.com/svelte/-/svelte-3.53.1.tgz#db9d7df7a8f570e8e22547444c149208b1914442"
|
||||
integrity sha512-Q4/hHkktZogGhN5iqxqSi9sjEVoe/NbIxX4hXEHoasTxj+TxEQVAq66LnDMdAZxjmsodkoI5F3slqsS68U7FNw==
|
||||
|
||||
svg-pan-zoom@3.6.1:
|
||||
version "3.6.1"
|
||||
@@ -5127,7 +5127,7 @@ tailwindcss@3.2.1:
|
||||
quick-lru "^5.1.1"
|
||||
resolve "^1.22.1"
|
||||
|
||||
tailwindcss@^3, tailwindcss@^3.1.3:
|
||||
tailwindcss@^3:
|
||||
version "3.1.8"
|
||||
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.1.8.tgz#4f8520550d67a835d32f2f4021580f9fddb7b741"
|
||||
integrity sha512-YSneUCZSFDYMwk+TGq8qYFdCA3yfBRdBlS7txSq0LUmzyeqRe3a8fBQzbz9M3WS/iFT4BNf/nmw9mEzrnSaC0g==
|
||||
@@ -5155,6 +5155,35 @@ tailwindcss@^3, tailwindcss@^3.1.3:
|
||||
quick-lru "^5.1.1"
|
||||
resolve "^1.22.1"
|
||||
|
||||
tailwindcss@^3.2.2:
|
||||
version "3.2.4"
|
||||
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.2.4.tgz#afe3477e7a19f3ceafb48e4b083e292ce0dc0250"
|
||||
integrity sha512-AhwtHCKMtR71JgeYDaswmZXhPcW9iuI9Sp2LvZPo9upDZ7231ZJ7eA9RaURbhpXGVlrjX4cFNlB4ieTetEb7hQ==
|
||||
dependencies:
|
||||
arg "^5.0.2"
|
||||
chokidar "^3.5.3"
|
||||
color-name "^1.1.4"
|
||||
detective "^5.2.1"
|
||||
didyoumean "^1.2.2"
|
||||
dlv "^1.1.3"
|
||||
fast-glob "^3.2.12"
|
||||
glob-parent "^6.0.2"
|
||||
is-glob "^4.0.3"
|
||||
lilconfig "^2.0.6"
|
||||
micromatch "^4.0.5"
|
||||
normalize-path "^3.0.0"
|
||||
object-hash "^3.0.0"
|
||||
picocolors "^1.0.0"
|
||||
postcss "^8.4.18"
|
||||
postcss-import "^14.1.0"
|
||||
postcss-js "^4.0.0"
|
||||
postcss-load-config "^3.1.4"
|
||||
postcss-nested "6.0.0"
|
||||
postcss-selector-parser "^6.0.10"
|
||||
postcss-value-parser "^4.2.0"
|
||||
quick-lru "^5.1.1"
|
||||
resolve "^1.22.1"
|
||||
|
||||
test-exclude@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e"
|
||||
@@ -5187,10 +5216,10 @@ tiny-glob@^0.2.9:
|
||||
globalyzer "0.1.0"
|
||||
globrex "^0.1.2"
|
||||
|
||||
tinybench@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.3.0.tgz#febb2e697c735c0cdb8eb1e43cb1d2fa1821f983"
|
||||
integrity sha512-zs1gMVBwyyG2QbVchYIbnabRhMOCGvrwZz/q+SV+LIMa9q5YDQZi2kkI6ZRqV2Bz7ba1uvrc7ieUoE4KWnGeKg==
|
||||
tinybench@^2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.3.1.tgz#14f64e6b77d7ef0b1f6ab850c7a808c6760b414d"
|
||||
integrity sha512-hGYWYBMPr7p4g5IarQE7XhlyWveh1EKhy4wUBS1LrHXCKYgvz+4/jCqgmJqZxxldesn05vccrtME2RLLZNW7iA==
|
||||
|
||||
tinypool@^0.3.0:
|
||||
version "0.3.0"
|
||||
@@ -5432,19 +5461,22 @@ vite@^3.0.0:
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
vitest@0.24.3:
|
||||
version "0.24.3"
|
||||
resolved "https://registry.yarnpkg.com/vitest/-/vitest-0.24.3.tgz#d91c7e2d557877d5270033efdf18add6063f0c97"
|
||||
integrity sha512-aM0auuPPgMSstWvr851hB74g/LKaKBzSxcG3da7ejfZbx08Y21JpZmbmDYrMTCGhVZKqTGwzcnLMwyfz2WzkhQ==
|
||||
vitest@0.25.1:
|
||||
version "0.25.1"
|
||||
resolved "https://registry.yarnpkg.com/vitest/-/vitest-0.25.1.tgz#4eafca68fabab22b6099451ab3fcaac33290a4ed"
|
||||
integrity sha512-eH74h6MkuEgsqR4mAQZeMK9O0PROiKY+i+1GMz/fBi5A3L2ml5U7JQs7LfPU7+uWUziZyLHagl+rkyfR8SLhlA==
|
||||
dependencies:
|
||||
"@types/chai" "^4.3.3"
|
||||
"@types/chai-subset" "^1.3.3"
|
||||
"@types/node" "*"
|
||||
acorn "^8.8.0"
|
||||
acorn-walk "^8.2.0"
|
||||
chai "^4.3.6"
|
||||
debug "^4.3.4"
|
||||
local-pkg "^0.4.2"
|
||||
source-map "^0.6.1"
|
||||
strip-literal "^0.4.2"
|
||||
tinybench "^2.3.0"
|
||||
tinybench "^2.3.1"
|
||||
tinypool "^0.3.0"
|
||||
tinyspy "^1.0.2"
|
||||
vite "^3.0.0"
|
||||
|
||||
Reference in New Issue
Block a user