Skip to content

Commit 877cbdb

Browse files
authored
Merge pull request #1570 from mermaid-js/release-promotion
Release live editor
2 parents d8401a8 + 83f3c07 commit 877cbdb

21 files changed

+971
-1312
lines changed

.eslintrc.cjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ module.exports = {
8686
j: true,
8787
k: true,
8888
param: true,
89+
Props: true,
8990
req: true,
9091
res: true,
9192
str: true,

.github/workflows/tests.yml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ jobs:
1717

1818
steps:
1919
- name: Checkout
20-
uses: actions/checkout@v3
20+
uses: actions/checkout@v4
2121

22-
- uses: actions/cache@v3
22+
- uses: actions/cache@v4
2323
id: yarn-and-build-cache
2424
with:
2525
path: |
@@ -30,21 +30,20 @@ jobs:
3030
restore-keys: |
3131
${{ runner.os }}-node_modules-build-
3232
33-
- uses: actions/setup-node@v3
33+
- uses: actions/setup-node@v4
3434
with:
35-
node-version: 18
35+
node-version-file: '.node-version'
3636
cache: 'yarn'
3737

3838
# Install NPM dependencies, cache them correctly
3939
# and run all Cypress tests
4040
- name: Cypress run
41-
uses: cypress-io/github-action@v3
41+
uses: cypress-io/github-action@v6
4242
with:
4343
build: yarn build
4444
start: yarn preview
4545
wait-on: 'http://localhost:3000'
4646
record: true
47-
headless: true
4847
parallel: true
4948
env:
5049
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}

.node-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
20.17.0
1+
20.18.0

package.json

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,50 +24,51 @@
2424
"devDependencies": {
2525
"@cypress/snapshot": "2.1.7",
2626
"@fortawesome/fontawesome-free": "^6.5.1",
27-
"@sveltejs/adapter-static": "3.0.4",
28-
"@sveltejs/kit": "2.5.26",
29-
"@sveltejs/vite-plugin-svelte": "^3.0.1",
30-
"@testing-library/svelte": "4.2.3",
27+
"@sveltejs/adapter-static": "3.0.6",
28+
"@sveltejs/kit": "2.8.0",
29+
"@sveltejs/vite-plugin-svelte": "^4.0.0",
30+
"@testing-library/jest-dom": "^6.6.3",
31+
"@testing-library/svelte": "^5.2.4",
3132
"@types/dompurify": "^3.0.5",
3233
"@types/lodash-es": "^4.17.12",
3334
"@types/pako": "2.0.3",
3435
"@types/uuid": "9.0.8",
3536
"@typescript-eslint/eslint-plugin": "6.21.0",
3637
"@typescript-eslint/parser": "6.21.0",
37-
"@vitest/ui": "^1.1.3",
38+
"@vitest/ui": "^2.1.4",
3839
"autoprefixer": "^10.4.14",
3940
"c8": "7.14.0",
4041
"chai": "^4.3.7",
4142
"cssnano": "^6.0.0",
4243
"cypress": "12.17.4",
4344
"cypress-localstorage-commands": "2.2.6",
44-
"eslint": "8.57.0",
45+
"eslint": "8.57.1",
4546
"eslint-config-prettier": "9.1.0",
4647
"eslint-plugin-cypress": "2.15.2",
4748
"eslint-plugin-es": "^4.1.0",
4849
"eslint-plugin-no-only-tests": "^3.1.0",
4950
"eslint-plugin-postcss-modules": "^2.0.0",
50-
"eslint-plugin-svelte": "^2.35.1",
51+
"eslint-plugin-svelte": "^2.45.1",
5152
"eslint-plugin-tailwindcss": "^3.13.1",
5253
"eslint-plugin-unicorn": "^50.0.1",
5354
"eslint-plugin-vitest": "^0.5.0",
5455
"esserializer": "^1.3.11",
5556
"husky": "^8.0.3",
56-
"jsdom": "^21.1.2",
57+
"jsdom": "^25.0.1",
5758
"lint-staged": "^15.2.0",
5859
"node-html-parser": "^6.1.5",
5960
"postcss": "^8.4.33",
6061
"postcss-load-config": "5.1.0",
6162
"prettier": "^3.1.0",
62-
"prettier-plugin-svelte": "^3.1.2",
63+
"prettier-plugin-svelte": "^3.2.6",
6364
"prettier-plugin-tailwindcss": "^0.6.0",
64-
"svelte": "^4.2.8",
65-
"svelte-preprocess": "^5.1.3",
65+
"svelte": "^5.0.0",
66+
"svelte-preprocess": "^6.0.0",
6667
"tailwindcss": "^3.4.1",
6768
"tslib": "^2.6.2",
68-
"typescript": "^5.3.3",
69-
"vite": "^5.0.11",
70-
"vitest": "^1.1.3",
69+
"typescript": "^5.5.0",
70+
"vite": "^5.4.4",
71+
"vitest": "^2.1.4",
7172
"vitest-dom": "^0.1.1"
7273
},
7374
"dependencies": {
@@ -79,11 +80,11 @@
7980
"js-base64": "3.7.7",
8081
"lodash-es": "^4.17.21",
8182
"mermaid": "^11.3.0",
82-
"monaco-editor": "0.51.0",
83+
"monaco-editor": "0.52.0",
8384
"pako": "2.1.0",
8485
"plausible-tracker": "^0.3.8",
8586
"random-word-slugs": "0.1.7",
86-
"svg-pan-zoom": "3.6.1",
87+
"svg-pan-zoom": "3.6.2",
8788
"svg2roughjs": "^3.2.0",
8889
"uuid": "9.0.1"
8990
},

src/lib/components/Actions.svelte

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
import { pakoSerde } from '$lib/util/serde';
77
import { stateStore } from '$lib/util/state';
88
import { logEvent } from '$lib/util/stats';
9+
import { version as FAVersion } from '@fortawesome/fontawesome-free/package.json';
910
import dayjs from 'dayjs';
1011
import { toBase64 } from 'js-base64';
11-
import { version as FAVersion } from '@fortawesome/fontawesome-free/package.json';
1212
1313
const FONT_AWESOME_URL = `https://cdnjs.cloudflare.com/ajax/libs/font-awesome/${FAVersion}/css/all.min.css`;
1414
@@ -149,7 +149,7 @@ ${svgString}`);
149149
logEvent('copyMarkdown');
150150
};
151151
152-
let gistURL = '';
152+
let gistURL = $state('');
153153
stateStore.subscribe(({ loader }) => {
154154
if (loader?.type === 'gist') {
155155
// @ts-expect-error Gist will have url
@@ -165,14 +165,14 @@ ${svgString}`);
165165
logEvent('loadGist');
166166
};
167167
168-
let iUrl: string;
169-
let svgUrl: string;
170-
let krokiUrl: string;
171-
let mdCode: string;
172-
let imagemodeselected = 'auto';
173-
let userimagesize = 1080;
168+
let iUrl: string | undefined = $state();
169+
let svgUrl: string | undefined = $state();
170+
let krokiUrl: string | undefined = $state();
171+
let mdCode: string | undefined = $state();
172+
let imagemodeselected = $state('auto');
173+
let userimagesize = $state(1080);
174174
175-
let isNetlify = false;
175+
let isNetlify = $state(false);
176176
if (browser && ['mermaid.live', 'netlify'].some((path) => window.location.host.includes(path))) {
177177
isNetlify = true;
178178
}
@@ -187,32 +187,32 @@ ${svgString}`);
187187
<Card title="Actions" isOpen={false}>
188188
<div class="m-2 flex flex-wrap gap-2">
189189
{#if isClipboardAvailable()}
190-
<button class="action-btn w-full" on:click={onCopyClipboard}
191-
><i class="far fa-copy mr-2" /> Copy Image to clipboard
190+
<button class="action-btn w-full" onclick={onCopyClipboard}
191+
><i class="far fa-copy mr-2"></i> Copy Image to clipboard
192192
</button>
193193
{/if}
194-
<button id="downloadPNG" class="action-btn flex-grow" on:click={onDownloadPNG}>
195-
<i class="fas fa-download mr-2" /> PNG
194+
<button id="downloadPNG" class="action-btn flex-grow" onclick={onDownloadPNG}>
195+
<i class="fas fa-download mr-2"></i> PNG
196196
</button>
197-
<button id="downloadSVG" class="action-btn flex-grow" on:click={onDownloadSVG}>
198-
<i class="fas fa-download mr-2" /> SVG
197+
<button id="downloadSVG" class="action-btn flex-grow" onclick={onDownloadSVG}>
198+
<i class="fas fa-download mr-2"></i> SVG
199199
</button>
200200
{#if rendererUrl}
201201
<a target="_blank" rel="noreferrer" class="flex-grow" href={iUrl}>
202202
<button class="action-btn w-full">
203-
<i class="fas fa-external-link-alt mr-2" /> PNG
203+
<i class="fas fa-external-link-alt mr-2"></i> PNG
204204
</button>
205205
</a>
206206
<a target="_blank" rel="noreferrer" class="flex-grow" href={svgUrl}>
207207
<button class="action-btn w-full">
208-
<i class="fas fa-external-link-alt mr-2" /> SVG
208+
<i class="fas fa-external-link-alt mr-2"></i> SVG
209209
</button>
210210
</a>
211211
{/if}
212212
{#if krokiRendererUrl}
213213
<a target="_blank" rel="noreferrer" class="flex-grow" href={krokiUrl}>
214214
<button class="action-btn w-full">
215-
<i class="fas fa-external-link-alt mr-2" /> Kroki
215+
<i class="fas fa-external-link-alt mr-2"></i> Kroki
216216
</button>
217217
</a>
218218
{/if}
@@ -244,9 +244,9 @@ ${svgString}`);
244244

245245
{#if rendererUrl}
246246
<div class="flex w-full items-center gap-2">
247-
<input class="input" id="markdown" type="text" value={mdCode} on:click={onCopyMarkdown} />
247+
<input class="input" id="markdown" type="text" value={mdCode} onclick={onCopyMarkdown} />
248248
<label for="markdown">
249-
<button class="btn btn-primary btn-md flex-auto" on:click={onCopyMarkdown}>
249+
<button class="btn btn-primary btn-md flex-auto" onclick={onCopyMarkdown}>
250250
Copy Markdown
251251
</button>
252252
</label>
@@ -261,7 +261,7 @@ ${svgString}`);
261261
bind:value={gistURL}
262262
placeholder="Enter Gist URL" />
263263
<label for="gist">
264-
<button class="btn btn-primary btn-md flex-auto" on:click={loadGist}> Load Gist </button>
264+
<button class="btn btn-primary btn-md flex-auto" onclick={loadGist}> Load Gist </button>
265265
</label>
266266
</div>
267267
{#if isNetlify}
Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,57 @@
11
<script lang="ts">
22
import type { Tab } from '$lib/types';
3+
import type { Snippet } from 'svelte';
34
import { slide } from 'svelte/transition';
45
import Tabs from './Tabs.svelte';
5-
export let isCloseable = true;
6-
export let isOpen = true;
7-
export let tabs: Tab[] = [];
8-
export let activeTabID = '';
9-
export let title: string;
10-
$: isOpen = isCloseable ? isOpen : true;
11-
$: isTabsShown = isOpen && tabs.length > 0;
6+
7+
interface Props {
8+
isClosable?: boolean;
9+
isOpen?: boolean;
10+
tabs?: Tab[];
11+
activeTabID?: string;
12+
title: string;
13+
onselect?: (tab: Tab) => void;
14+
actions?: Snippet;
15+
children?: Snippet;
16+
}
17+
18+
let {
19+
isClosable = true,
20+
isOpen = true,
21+
tabs = [],
22+
activeTabID = '',
23+
title,
24+
onselect,
25+
actions,
26+
children
27+
}: Props = $props();
28+
29+
const toggleCardOpen = () => {
30+
if (isClosable) {
31+
isOpen = !isOpen;
32+
}
33+
};
34+
35+
let isTabsShown = $derived(isOpen && tabs.length > 0);
1236
</script>
1337

1438
<div class="card m-2 flex flex-grow flex-col overflow-hidden rounded shadow-2xl">
1539
<div
1640
role="toolbar"
1741
tabindex="0"
1842
class="bg-primary p-2 {isTabsShown ? 'pb-0' : ''} flex-none cursor-pointer"
19-
on:click={() => (isOpen = !isOpen)}
20-
on:keypress={() => (isOpen = !isOpen)}>
43+
onclick={toggleCardOpen}
44+
onkeypress={toggleCardOpen}>
2145
<div class="flex justify-between">
22-
<Tabs on:select {tabs} bind:isOpen {title} {isCloseable} {activeTabID} />
46+
<Tabs {onselect} {tabs} bind:isOpen {title} {isClosable} {activeTabID} />
2347
<div class="flex items-center gap-x-4 {isTabsShown ? '-mt-2' : ''}">
24-
<slot name="actions" />
48+
{@render actions?.()}
2549
</div>
2650
</div>
2751
</div>
2852
{#if isOpen}
2953
<div class="card-body flex-grow overflow-auto p-0 text-base-content" transition:slide>
30-
<slot />
54+
{@render children?.()}
3155
</div>
3256
{/if}
3357
</div>

src/lib/components/Card/Tabs.svelte

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,53 @@
11
<script lang="ts">
2-
import type { Tab, TabEvents } from '$lib/types';
3-
import { createEventDispatcher } from 'svelte';
2+
import type { Tab } from '$lib/types';
43
import { fade } from 'svelte/transition';
5-
export let isCloseable = true;
6-
export let tabs: Tab[];
7-
export let title: string;
8-
export let isOpen = false;
9-
export let activeTabID: string;
4+
5+
let {
6+
isClosable = true,
7+
tabs,
8+
title,
9+
isOpen = $bindable(false),
10+
activeTabID = $bindable(),
11+
onselect
12+
}: {
13+
isClosable?: boolean;
14+
tabs: Tab[];
15+
title: string;
16+
isOpen?: boolean;
17+
activeTabID: string;
18+
onselect?: (tab: Tab) => void;
19+
} = $props();
1020
1121
if (!activeTabID && tabs.length > 0) {
1222
activeTabID = tabs[0].id;
1323
}
14-
const dispatch = createEventDispatcher<TabEvents>();
24+
1525
const toggleTabs = (tab: Tab) => {
16-
activeTabID = tab.id;
17-
dispatch('select', tab);
26+
return (event: Event) => {
27+
event.stopPropagation();
28+
activeTabID = tab.id;
29+
onselect?.(tab);
30+
};
1831
};
1932
</script>
2033

2134
<div class="flex cursor-default">
22-
<span
23-
role="menubar"
24-
tabindex="0"
25-
class="mr-2 font-semibold"
26-
on:click|stopPropagation={() => (isOpen = !isOpen)}
27-
on:keypress|stopPropagation={() => (isOpen = !isOpen)}>
28-
{#if isCloseable}
29-
<i class="fas fa-chevron-right icon" class:isOpen />
35+
<span role="menubar" tabindex="0" class="mr-2 font-semibold">
36+
{#if isClosable}
37+
<i class="fas fa-chevron-right icon mr-1" class:isOpen></i>
3038
{/if}
31-
{title}</span>
39+
{title}
40+
</span>
3241
{#if isOpen && tabs}
3342
<ul class="tabs" transition:fade>
3443
{#each tabs as tab}
3544
<div
3645
role="tab"
3746
tabindex="0"
3847
class="tab tab-lifted {activeTabID === tab.id ? 'tab-active' : 'text-primary-content'}"
39-
on:click|stopPropagation={() => toggleTabs(tab)}
40-
on:keypress|stopPropagation={() => toggleTabs(tab)}>
41-
<i class="mr-1 {tab.icon}" />
48+
onclick={toggleTabs(tab)}
49+
onkeypress={toggleTabs(tab)}>
50+
<i class="mr-1 {tab.icon}"></i>
4251
{tab.title}
4352
</div>
4453
{/each}

src/lib/components/Card/card.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { cleanup, render } from '@testing-library/svelte';
2-
import { describe, expect, it, afterEach } from 'vitest';
2+
import { afterEach, describe, expect, it } from 'vitest';
33
import Card from './Card.svelte';
44

55
describe('card.svelte', () => {

0 commit comments

Comments
 (0)