Merge pull request #1776 from mermaid-js/release-promotion
Release live editor
This commit is contained in:
Vendored
+5
-1
@@ -47,5 +47,9 @@
|
||||
"tailwindCSS.experimental.classRegex": [
|
||||
["([\"'`][^\"'`]*.*?[\"'`])", "[\"'`]([^\"'`]*).*?[\"'`]"]
|
||||
],
|
||||
"tailwindCSS.emmetCompletions": true
|
||||
"tailwindCSS.emmetCompletions": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit",
|
||||
"source.organizeImports": "explicit"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
import Card from '$/components/Card/Card.svelte';
|
||||
import CopyButton from '$/components/CopyButton.svelte';
|
||||
import CopyInput from '$/components/CopyInput.svelte';
|
||||
import ExternalLinkWrapper from '$/components/ExternalLinkWrapper.svelte';
|
||||
import { Button } from '$/components/ui/button';
|
||||
import { Input } from '$/components/ui/input';
|
||||
import { Separator } from '$/components/ui/separator';
|
||||
import * as ToggleGroup from '$/components/ui/toggle-group';
|
||||
import { TID } from '$/constants';
|
||||
import { env } from '$/util/env';
|
||||
import { getDomain } from '$/util/util';
|
||||
import { browser } from '$app/environment';
|
||||
import { waitForRender } from '$lib/util/autoSync';
|
||||
import { inputStateStore, stateStore, urlsStore } from '$lib/util/state';
|
||||
@@ -204,11 +205,11 @@ ${svgString}`);
|
||||
<DownloadIcon />
|
||||
{text}
|
||||
</Button>
|
||||
{#if url}
|
||||
<ExternalLinkWrapper domain={getDomain(url)} isVisible={!!url}>
|
||||
<Button class="rounded-l-none" href={url} target="_blank" rel="noreferrer noopener">
|
||||
<ExternalLinkIcon />
|
||||
</Button>
|
||||
{/if}
|
||||
</ExternalLinkWrapper>
|
||||
</div>
|
||||
{/snippet}
|
||||
|
||||
@@ -235,22 +236,24 @@ ${svgString}`);
|
||||
<div class="flex gap-2">
|
||||
{@render dualActionButton('PNG', onDownloadPNG, $urlsStore.png)}
|
||||
{@render dualActionButton('SVG', onDownloadSVG, $urlsStore.svg)}
|
||||
{#if env.krokiRendererUrl}
|
||||
<ExternalLinkWrapper domain={getDomain($urlsStore.kroki)} isVisible={!!$urlsStore.kroki}>
|
||||
<a target="_blank" rel="noreferrer" class="flex-grow" href={$urlsStore.kroki}>
|
||||
<Button class="action-btn flex w-full items-center gap-2">
|
||||
<ExternalLinkIcon /> Kroki
|
||||
</Button>
|
||||
</a>
|
||||
{/if}
|
||||
</ExternalLinkWrapper>
|
||||
</div>
|
||||
<Separator />
|
||||
{#if isClipboardAvailable()}
|
||||
<CopyButton onclick={onCopyClipboard} label="Copy Image" />
|
||||
{/if}
|
||||
{#if $urlsStore.mdCode}
|
||||
<ExternalLinkWrapper
|
||||
labelPrefix="Thumbnail generated by"
|
||||
domain={getDomain($urlsStore.png)}
|
||||
isVisible={!!$urlsStore.mdCode}>
|
||||
<CopyInput value={$urlsStore.mdCode} label="Copy Markdown" testID={TID.copyMarkdown} />
|
||||
{/if}
|
||||
|
||||
</ExternalLinkWrapper>
|
||||
<div class="flex w-full items-center gap-2">
|
||||
<Input type="url" bind:value={gistURL} placeholder="Enter Gist URL" />
|
||||
<Button onclick={loadGist}>Load Gist</Button>
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
<script lang="ts">
|
||||
import { stateStore } from '$/util/state';
|
||||
import * as Tooltip from '$lib/components/ui/tooltip';
|
||||
import type { ComponentProps, Snippet } from 'svelte';
|
||||
import ExternalLinkIcon from '~icons/material-symbols/open-in-new-rounded';
|
||||
|
||||
let {
|
||||
children,
|
||||
domain,
|
||||
shouldCheckDiagramType = true,
|
||||
side = 'bottom',
|
||||
labelPrefix = 'Opens your diagram in',
|
||||
isVisible = true,
|
||||
sharesData = true
|
||||
}: {
|
||||
children: Snippet;
|
||||
domain: string;
|
||||
shouldCheckDiagramType?: boolean;
|
||||
side?: ComponentProps<typeof Tooltip.Content>['side'];
|
||||
labelPrefix?: string;
|
||||
isVisible?: boolean;
|
||||
sharesData?: boolean;
|
||||
} = $props();
|
||||
|
||||
let shouldDisableComponent = $derived(
|
||||
shouldCheckDiagramType && $stateStore.diagramType === 'zenuml'
|
||||
);
|
||||
</script>
|
||||
|
||||
{#if isVisible}
|
||||
<Tooltip.Provider>
|
||||
<Tooltip.Root delayDuration={100}>
|
||||
<Tooltip.Trigger>
|
||||
<div class={[shouldDisableComponent && 'pointer-events-none cursor-not-allowed grayscale']}>
|
||||
{@render children()}
|
||||
</div>
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Content {side} class="bg-secondary shadow-xl">
|
||||
<div
|
||||
class="flex cursor-help items-center gap-2"
|
||||
title={sharesData
|
||||
? 'Your diagram will be sent to the external service'
|
||||
: 'Your diagram is not shared'}>
|
||||
{#if shouldDisableComponent}
|
||||
<div class="text-muted-foreground">
|
||||
This diagram type is not supported in {domain}
|
||||
</div>
|
||||
{:else}
|
||||
<ExternalLinkIcon />
|
||||
<span class="flex items-center gap-1">
|
||||
{labelPrefix}
|
||||
<div class="text-accent">{domain}</div>
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Root>
|
||||
</Tooltip.Provider>
|
||||
{/if}
|
||||
@@ -29,16 +29,18 @@
|
||||
href: $urlsStore.mermaidChart({ medium: 'main_menu' }).playground
|
||||
},
|
||||
{
|
||||
label: 'Plugins',
|
||||
icon: PluginIcon,
|
||||
checkDiagramType: false,
|
||||
href: $urlsStore.mermaidChart({ medium: 'main_menu' }).plugins,
|
||||
checkDiagramType: false
|
||||
icon: PluginIcon,
|
||||
label: 'Plugins',
|
||||
sharesData: false
|
||||
},
|
||||
{
|
||||
label: 'MermaidChart',
|
||||
icon: MermaidChartIcon,
|
||||
checkDiagramType: false,
|
||||
href: $urlsStore.mermaidChart({ medium: 'main_menu' }).home,
|
||||
checkDiagramType: false
|
||||
icon: MermaidChartIcon,
|
||||
label: 'MermaidChart',
|
||||
sharesData: false
|
||||
}
|
||||
]);
|
||||
</script>
|
||||
@@ -76,7 +78,11 @@
|
||||
</div>
|
||||
|
||||
{#each mermaidChartMenuItems as item}
|
||||
<McWrapper side="right" shouldCheckDiagramType={item.checkDiagramType}>
|
||||
<McWrapper
|
||||
side="right"
|
||||
labelPrefix={item.sharesData === false ? 'Opens a new tab in' : undefined}
|
||||
sharesData={item.sharesData}
|
||||
shouldCheckDiagramType={item.checkDiagramType}>
|
||||
{@render menuItem({
|
||||
...item,
|
||||
class: 'text-accent bg-background hover:bg-muted'
|
||||
|
||||
@@ -1,50 +1,17 @@
|
||||
<script lang="ts">
|
||||
import { env } from '$/util/env';
|
||||
import { stateStore } from '$/util/state';
|
||||
import * as Tooltip from '$lib/components/ui/tooltip';
|
||||
import type { ComponentProps, Snippet } from 'svelte';
|
||||
import ExternalLinkIcon from '~icons/material-symbols/open-in-new-rounded';
|
||||
import type { ComponentProps } from 'svelte';
|
||||
import ExternalLinkWrapper from './ExternalLinkWrapper.svelte';
|
||||
|
||||
let {
|
||||
children,
|
||||
shouldCheckDiagramType = true,
|
||||
side = 'bottom',
|
||||
labelPrefix = 'Opens a new tab in'
|
||||
}: {
|
||||
children: Snippet;
|
||||
shouldCheckDiagramType?: boolean;
|
||||
side?: ComponentProps<typeof Tooltip.Content>['side'];
|
||||
labelPrefix?: string;
|
||||
} = $props();
|
||||
|
||||
let shouldDisableComponent = $derived(
|
||||
shouldCheckDiagramType && $stateStore.diagramType === 'zenuml'
|
||||
);
|
||||
...props
|
||||
}: Omit<ComponentProps<typeof ExternalLinkWrapper>, 'isVisible' | 'domain'> = $props();
|
||||
</script>
|
||||
|
||||
{#if env.isEnabledMermaidChartLinks}
|
||||
<Tooltip.Provider>
|
||||
<Tooltip.Root delayDuration={100}>
|
||||
<Tooltip.Trigger>
|
||||
<div class={[shouldDisableComponent && 'pointer-events-none cursor-not-allowed grayscale']}>
|
||||
{@render children()}
|
||||
</div>
|
||||
</Tooltip.Trigger>
|
||||
<Tooltip.Content {side}>
|
||||
<div class="flex items-center gap-2">
|
||||
{#if shouldDisableComponent}
|
||||
<div class="text-muted-foreground">
|
||||
This diagram type is not supported in MermaidChart.com
|
||||
</div>
|
||||
{:else}
|
||||
<ExternalLinkIcon />
|
||||
<span class="flex items-center gap-1">
|
||||
{labelPrefix}
|
||||
<div class="text-accent">MermaidChart.com</div>
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
</Tooltip.Content>
|
||||
</Tooltip.Root>
|
||||
</Tooltip.Provider>
|
||||
{/if}
|
||||
<ExternalLinkWrapper
|
||||
{...props}
|
||||
domain="MermaidChart.com"
|
||||
isVisible={env.isEnabledMermaidChartLinks}>
|
||||
{@render children()}
|
||||
</ExternalLinkWrapper>
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
Live Editor
|
||||
</a>
|
||||
|
||||
<McWrapper labelPrefix="Opens the current diagram in">
|
||||
<McWrapper>
|
||||
<div class="hidden items-center justify-center gap-4 md:flex">
|
||||
<Separator orientation="vertical" />
|
||||
<Switch
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script>
|
||||
import ExternalLinkWrapper from '$/components/ExternalLinkWrapper.svelte';
|
||||
import * as Dialog from '$/components/ui/dialog';
|
||||
import ShieldIcon from '~icons/material-symbols/shield-lock-outline-rounded';
|
||||
</script>
|
||||
@@ -7,7 +8,7 @@
|
||||
<Dialog.Trigger>
|
||||
<ShieldIcon />
|
||||
</Dialog.Trigger>
|
||||
<Dialog.Content class="max-h-full overflow-y-auto">
|
||||
<Dialog.Content class="max-h-full overflow-hidden overflow-y-auto p-12">
|
||||
<Dialog.Header>
|
||||
<Dialog.Title class="flex items-center gap-2 text-xl">
|
||||
<ShieldIcon class="size-8 text-green-700" />
|
||||
@@ -15,39 +16,30 @@
|
||||
</Dialog.Title>
|
||||
</Dialog.Header>
|
||||
|
||||
<p class="text-xl font-semibold">
|
||||
The content of the diagrams you create never leaves your browser.
|
||||
</p>
|
||||
<p>It's only stored in the URL, and your browser's local storage.</p>
|
||||
<p class="text-xl font-semibold">Your diagrams never leave your browser.</p>
|
||||
<p>They're only stored in the URL and your browser's local storage.</p>
|
||||
<p>
|
||||
Mermaid Live Editor is a fully open source, client side application, deployed transparently on <a
|
||||
This is a fully open source, client-side app deployed on <a
|
||||
href="https://github.com/mermaid-js/mermaid-live-editor/deployments"
|
||||
class="underline"
|
||||
target="_blank">
|
||||
GitHub Pages
|
||||
</a>.
|
||||
target="_blank">GitHub Pages</a>
|
||||
that works offline as a
|
||||
<a href="https://web.dev/explore/progressive-web-apps" target="_blank">Progressive Web App</a
|
||||
>.
|
||||
</p>
|
||||
<p>
|
||||
It will also work as a fully offline
|
||||
<a href="https://web.dev/explore/progressive-web-apps" target="_blank">
|
||||
Progressive Web App.
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
The only server we have is a self hosted version of the open source and privacy friendly
|
||||
Plausible Analytics. We only collect anonymous data related to actions performed, like the
|
||||
type of diagram rendered, number of times a feature was used, etc.
|
||||
</p>
|
||||
<p>
|
||||
All the data we collect is anonymized and
|
||||
<a href="https://p.mermaid.live/mermaid.live" class="underline" target="_blank">
|
||||
available publicly.
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Additional services like the external PNG/SVG/Kroki links and "Save to Mermaid Chart" feature
|
||||
will share your diagram with the respective 3rd party service.
|
||||
We use self hosted, privacy-friendly Plausible Analytics to collect anonymous usage metadata
|
||||
(diagram types, feature usage, etc.). All data is <a
|
||||
href="https://p.mermaid.live/mermaid.live"
|
||||
class="underline"
|
||||
target="_blank">publicly available</a
|
||||
>.
|
||||
</p>
|
||||
<ExternalLinkWrapper domain="example.com" isVisible>
|
||||
<p class="text-left">
|
||||
External services (PNG/SVG/Kroki exports, "Save to Mermaid Chart", "Repair with AI", etc)
|
||||
will share your diagram with those 3rd parties, and are highlighted in the UI on hover.
|
||||
</p>
|
||||
</ExternalLinkWrapper>
|
||||
</Dialog.Content>
|
||||
</Dialog.Root>
|
||||
|
||||
@@ -5,6 +5,12 @@ import { applyMigrations } from './migrations';
|
||||
import { initURLSubscription, loadState, updateCodeStore, verifyState } from './state';
|
||||
import { initAnalytics, plausible } from './stats';
|
||||
|
||||
export const getDomain = (url?: string): string => {
|
||||
if (!url) return '';
|
||||
const domain = new URL(url).hostname;
|
||||
return domain;
|
||||
};
|
||||
|
||||
export const loadStateFromURL = (): void => {
|
||||
loadState(window.location.hash.slice(1));
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user