markstream-svelte 0.0.1-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +77 -0
- package/dist/components/AdmonitionNode.svelte +8 -0
- package/dist/components/AdmonitionNode.svelte.d.ts +23 -0
- package/dist/components/AdmonitionNode.svelte.d.ts.map +1 -0
- package/dist/components/BlockquoteNode.svelte +10 -0
- package/dist/components/BlockquoteNode.svelte.d.ts +24 -0
- package/dist/components/BlockquoteNode.svelte.d.ts.map +1 -0
- package/dist/components/CheckboxNode.svelte +5 -0
- package/dist/components/CheckboxNode.svelte.d.ts +22 -0
- package/dist/components/CheckboxNode.svelte.d.ts.map +1 -0
- package/dist/components/CodeBlockNode.svelte +944 -0
- package/dist/components/CodeBlockNode.svelte.d.ts +43 -0
- package/dist/components/CodeBlockNode.svelte.d.ts.map +1 -0
- package/dist/components/D2BlockNode.svelte +272 -0
- package/dist/components/D2BlockNode.svelte.d.ts +33 -0
- package/dist/components/D2BlockNode.svelte.d.ts.map +1 -0
- package/dist/components/DefinitionListNode.svelte +8 -0
- package/dist/components/DefinitionListNode.svelte.d.ts +23 -0
- package/dist/components/DefinitionListNode.svelte.d.ts.map +1 -0
- package/dist/components/EmojiNode.svelte +7 -0
- package/dist/components/EmojiNode.svelte.d.ts +22 -0
- package/dist/components/EmojiNode.svelte.d.ts.map +1 -0
- package/dist/components/EmphasisNode.svelte +8 -0
- package/dist/components/EmphasisNode.svelte.d.ts +24 -0
- package/dist/components/EmphasisNode.svelte.d.ts.map +1 -0
- package/dist/components/FallbackComponent.svelte +8 -0
- package/dist/components/FallbackComponent.svelte.d.ts +23 -0
- package/dist/components/FallbackComponent.svelte.d.ts.map +1 -0
- package/dist/components/FootnoteAnchorNode.svelte +21 -0
- package/dist/components/FootnoteAnchorNode.svelte.d.ts +22 -0
- package/dist/components/FootnoteAnchorNode.svelte.d.ts.map +1 -0
- package/dist/components/FootnoteNode.svelte +19 -0
- package/dist/components/FootnoteNode.svelte.d.ts +24 -0
- package/dist/components/FootnoteNode.svelte.d.ts.map +1 -0
- package/dist/components/FootnoteReferenceNode.svelte +26 -0
- package/dist/components/FootnoteReferenceNode.svelte.d.ts +22 -0
- package/dist/components/FootnoteReferenceNode.svelte.d.ts.map +1 -0
- package/dist/components/HardBreakNode.svelte +1 -0
- package/dist/components/HardBreakNode.svelte.d.ts +27 -0
- package/dist/components/HardBreakNode.svelte.d.ts.map +1 -0
- package/dist/components/HeadingNode.svelte +15 -0
- package/dist/components/HeadingNode.svelte.d.ts +24 -0
- package/dist/components/HeadingNode.svelte.d.ts.map +1 -0
- package/dist/components/HighlightNode.svelte +8 -0
- package/dist/components/HighlightNode.svelte.d.ts +24 -0
- package/dist/components/HighlightNode.svelte.d.ts.map +1 -0
- package/dist/components/HtmlBlockNode.svelte +8 -0
- package/dist/components/HtmlBlockNode.svelte.d.ts +23 -0
- package/dist/components/HtmlBlockNode.svelte.d.ts.map +1 -0
- package/dist/components/HtmlInlineNode.svelte +8 -0
- package/dist/components/HtmlInlineNode.svelte.d.ts +23 -0
- package/dist/components/HtmlInlineNode.svelte.d.ts.map +1 -0
- package/dist/components/HtmlPreviewFrame.svelte +13 -0
- package/dist/components/HtmlPreviewFrame.svelte.d.ts +26 -0
- package/dist/components/HtmlPreviewFrame.svelte.d.ts.map +1 -0
- package/dist/components/ImageNode.svelte +86 -0
- package/dist/components/ImageNode.svelte.d.ts +25 -0
- package/dist/components/ImageNode.svelte.d.ts.map +1 -0
- package/dist/components/InfographicBlockNode.svelte +429 -0
- package/dist/components/InfographicBlockNode.svelte.d.ts +34 -0
- package/dist/components/InfographicBlockNode.svelte.d.ts.map +1 -0
- package/dist/components/InlineCodeNode.svelte +7 -0
- package/dist/components/InlineCodeNode.svelte.d.ts +22 -0
- package/dist/components/InlineCodeNode.svelte.d.ts.map +1 -0
- package/dist/components/InlineWrapNode.svelte +10 -0
- package/dist/components/InlineWrapNode.svelte.d.ts +25 -0
- package/dist/components/InlineWrapNode.svelte.d.ts.map +1 -0
- package/dist/components/InsertNode.svelte +8 -0
- package/dist/components/InsertNode.svelte.d.ts +24 -0
- package/dist/components/InsertNode.svelte.d.ts.map +1 -0
- package/dist/components/LinkNode.svelte +41 -0
- package/dist/components/LinkNode.svelte.d.ts +25 -0
- package/dist/components/LinkNode.svelte.d.ts.map +1 -0
- package/dist/components/ListItemNode.svelte +9 -0
- package/dist/components/ListItemNode.svelte.d.ts +24 -0
- package/dist/components/ListItemNode.svelte.d.ts.map +1 -0
- package/dist/components/ListNode.svelte +16 -0
- package/dist/components/ListNode.svelte.d.ts +24 -0
- package/dist/components/ListNode.svelte.d.ts.map +1 -0
- package/dist/components/MarkdownCodeBlockNode.svelte +7 -0
- package/dist/components/MarkdownCodeBlockNode.svelte.d.ts +23 -0
- package/dist/components/MarkdownCodeBlockNode.svelte.d.ts.map +1 -0
- package/dist/components/MathBlockNode.svelte +96 -0
- package/dist/components/MathBlockNode.svelte.d.ts +22 -0
- package/dist/components/MathBlockNode.svelte.d.ts.map +1 -0
- package/dist/components/MathInlineNode.svelte +103 -0
- package/dist/components/MathInlineNode.svelte.d.ts +22 -0
- package/dist/components/MathInlineNode.svelte.d.ts.map +1 -0
- package/dist/components/MermaidBlockNode.svelte +557 -0
- package/dist/components/MermaidBlockNode.svelte.d.ts +40 -0
- package/dist/components/MermaidBlockNode.svelte.d.ts.map +1 -0
- package/dist/components/NodeOutlet.svelte +192 -0
- package/dist/components/NodeOutlet.svelte.d.ts +24 -0
- package/dist/components/NodeOutlet.svelte.d.ts.map +1 -0
- package/dist/components/NodeRenderer.svelte +349 -0
- package/dist/components/NodeRenderer.svelte.d.ts +64 -0
- package/dist/components/NodeRenderer.svelte.d.ts.map +1 -0
- package/dist/components/ParagraphNode.svelte +21 -0
- package/dist/components/ParagraphNode.svelte.d.ts +24 -0
- package/dist/components/ParagraphNode.svelte.d.ts.map +1 -0
- package/dist/components/PreCodeNode.svelte +13 -0
- package/dist/components/PreCodeNode.svelte.d.ts +22 -0
- package/dist/components/PreCodeNode.svelte.d.ts.map +1 -0
- package/dist/components/ReferenceNode.svelte +8 -0
- package/dist/components/ReferenceNode.svelte.d.ts +23 -0
- package/dist/components/ReferenceNode.svelte.d.ts.map +1 -0
- package/dist/components/RenderChildren.svelte +12 -0
- package/dist/components/RenderChildren.svelte.d.ts +24 -0
- package/dist/components/RenderChildren.svelte.d.ts.map +1 -0
- package/dist/components/StrikethroughNode.svelte +8 -0
- package/dist/components/StrikethroughNode.svelte.d.ts +24 -0
- package/dist/components/StrikethroughNode.svelte.d.ts.map +1 -0
- package/dist/components/StrongNode.svelte +8 -0
- package/dist/components/StrongNode.svelte.d.ts +24 -0
- package/dist/components/StrongNode.svelte.d.ts.map +1 -0
- package/dist/components/SubscriptNode.svelte +8 -0
- package/dist/components/SubscriptNode.svelte.d.ts +24 -0
- package/dist/components/SubscriptNode.svelte.d.ts.map +1 -0
- package/dist/components/SuperscriptNode.svelte +8 -0
- package/dist/components/SuperscriptNode.svelte.d.ts +24 -0
- package/dist/components/SuperscriptNode.svelte.d.ts.map +1 -0
- package/dist/components/TableNode.svelte +8 -0
- package/dist/components/TableNode.svelte.d.ts +23 -0
- package/dist/components/TableNode.svelte.d.ts.map +1 -0
- package/dist/components/TextNode.svelte +37 -0
- package/dist/components/TextNode.svelte.d.ts +25 -0
- package/dist/components/TextNode.svelte.d.ts.map +1 -0
- package/dist/components/ThematicBreakNode.svelte +1 -0
- package/dist/components/ThematicBreakNode.svelte.d.ts +27 -0
- package/dist/components/ThematicBreakNode.svelte.d.ts.map +1 -0
- package/dist/components/Tooltip.svelte +4 -0
- package/dist/components/Tooltip.svelte.d.ts +21 -0
- package/dist/components/Tooltip.svelte.d.ts.map +1 -0
- package/dist/components/VmrContainerNode.svelte +8 -0
- package/dist/components/VmrContainerNode.svelte.d.ts +23 -0
- package/dist/components/VmrContainerNode.svelte.d.ts.map +1 -0
- package/dist/components/shared/diagram-height.d.ts +10 -0
- package/dist/components/shared/diagram-height.d.ts.map +1 -0
- package/dist/components/shared/diagram-height.js +52 -0
- package/dist/components/shared/node-helpers.d.ts +108 -0
- package/dist/components/shared/node-helpers.d.ts.map +1 -0
- package/dist/components/shared/node-helpers.js +220 -0
- package/dist/components/shared/node-outlet-helpers.d.ts +9 -0
- package/dist/components/shared/node-outlet-helpers.d.ts.map +1 -0
- package/dist/components/shared/node-outlet-helpers.js +92 -0
- package/dist/components/shared/render-window.d.ts +19 -0
- package/dist/components/shared/render-window.d.ts.map +1 -0
- package/dist/components/shared/render-window.js +63 -0
- package/dist/components/shared/renderNodeHtml.d.ts +4 -0
- package/dist/components/shared/renderNodeHtml.d.ts.map +1 -0
- package/dist/components/shared/renderNodeHtml.js +19 -0
- package/dist/components/shared/rich-block-helpers.d.ts +7 -0
- package/dist/components/shared/rich-block-helpers.d.ts.map +1 -0
- package/dist/components/shared/rich-block-helpers.js +76 -0
- package/dist/customComponents.d.ts +10 -0
- package/dist/customComponents.d.ts.map +1 -0
- package/dist/customComponents.js +66 -0
- package/dist/enhanceRenderedHtml.d.ts +21 -0
- package/dist/enhanceRenderedHtml.d.ts.map +1 -0
- package/dist/enhanceRenderedHtml.js +768 -0
- package/dist/hydrateCustomTagContent.d.ts +3 -0
- package/dist/hydrateCustomTagContent.d.ts.map +1 -0
- package/dist/hydrateCustomTagContent.js +130 -0
- package/dist/i18n/useSafeI18n.d.ts +5 -0
- package/dist/i18n/useSafeI18n.d.ts.map +1 -0
- package/dist/i18n/useSafeI18n.js +42 -0
- package/dist/index.css +2009 -0
- package/dist/index.d.ts +78 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +66 -0
- package/dist/index.px.css +2009 -0
- package/dist/index.tailwind.css +2009 -0
- package/dist/optional/d2.d.ts +7 -0
- package/dist/optional/d2.d.ts.map +1 -0
- package/dist/optional/d2.js +67 -0
- package/dist/optional/infographic.d.ts +2 -0
- package/dist/optional/infographic.d.ts.map +1 -0
- package/dist/optional/infographic.js +29 -0
- package/dist/optional/katex.d.ts +7 -0
- package/dist/optional/katex.d.ts.map +1 -0
- package/dist/optional/katex.js +93 -0
- package/dist/optional/mermaid.d.ts +7 -0
- package/dist/optional/mermaid.d.ts.map +1 -0
- package/dist/optional/mermaid.js +171 -0
- package/dist/optional/monaco.d.ts +5 -0
- package/dist/optional/monaco.d.ts.map +1 -0
- package/dist/optional/monaco.js +70 -0
- package/dist/parseNestedMarkdownToNodes.d.ts +15 -0
- package/dist/parseNestedMarkdownToNodes.d.ts.map +1 -0
- package/dist/parseNestedMarkdownToNodes.js +66 -0
- package/dist/renderMarkdownHtml.d.ts +31 -0
- package/dist/renderMarkdownHtml.d.ts.map +1 -0
- package/dist/renderMarkdownHtml.js +465 -0
- package/dist/sanitizeHtmlContent.d.ts +3 -0
- package/dist/sanitizeHtmlContent.d.ts.map +1 -0
- package/dist/sanitizeHtmlContent.js +175 -0
- package/dist/sanitizeSvg.d.ts +3 -0
- package/dist/sanitizeSvg.d.ts.map +1 -0
- package/dist/sanitizeSvg.js +76 -0
- package/dist/tailwind-entry.d.ts +2 -0
- package/dist/tailwind-entry.d.ts.map +1 -0
- package/dist/tailwind-entry.js +1 -0
- package/dist/tooltip/singletonTooltip.d.ts +8 -0
- package/dist/tooltip/singletonTooltip.d.ts.map +1 -0
- package/dist/tooltip/singletonTooltip.js +124 -0
- package/dist/types/monaco.d.ts +66 -0
- package/dist/types/monaco.d.ts.map +1 -0
- package/dist/types/monaco.js +1 -0
- package/dist/utils/languageIcon.d.ts +8 -0
- package/dist/utils/languageIcon.d.ts.map +1 -0
- package/dist/utils/languageIcon.js +182 -0
- package/dist/utils/normalizeKaTeXRenderInput.d.ts +2 -0
- package/dist/utils/normalizeKaTeXRenderInput.d.ts.map +1 -0
- package/dist/utils/normalizeKaTeXRenderInput.js +7 -0
- package/dist/workers/katexCdnWorker.d.ts +21 -0
- package/dist/workers/katexCdnWorker.d.ts.map +1 -0
- package/dist/workers/katexCdnWorker.js +193 -0
- package/dist/workers/katexRenderer.worker.d.ts +2 -0
- package/dist/workers/katexRenderer.worker.d.ts.map +1 -0
- package/dist/workers/katexRenderer.worker.js +55 -0
- package/dist/workers/katexWorkerClient.d.ts +36 -0
- package/dist/workers/katexWorkerClient.d.ts.map +1 -0
- package/dist/workers/katexWorkerClient.js +270 -0
- package/dist/workers/mermaidCdnWorker.d.ts +16 -0
- package/dist/workers/mermaidCdnWorker.d.ts.map +1 -0
- package/dist/workers/mermaidCdnWorker.js +235 -0
- package/dist/workers/mermaidParser.worker.d.ts +2 -0
- package/dist/workers/mermaidParser.worker.d.ts.map +1 -0
- package/dist/workers/mermaidParser.worker.js +85 -0
- package/dist/workers/mermaidWorkerClient.d.ts +16 -0
- package/dist/workers/mermaidWorkerClient.d.ts.map +1 -0
- package/dist/workers/mermaidWorkerClient.js +170 -0
- package/package.json +95 -0
|
@@ -0,0 +1,557 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { SvelteRenderableNode, SvelteRenderContext } from './shared/node-helpers'
|
|
3
|
+
import { afterUpdate, onDestroy, onMount } from 'svelte'
|
|
4
|
+
import { useSafeI18n } from '../i18n/useSafeI18n'
|
|
5
|
+
import { getMermaid } from '../optional/mermaid'
|
|
6
|
+
import { toSafeSvgMarkup } from '../sanitizeSvg'
|
|
7
|
+
import { hideTooltip, showTooltipForAnchor, type TooltipPlacement } from '../tooltip/singletonTooltip'
|
|
8
|
+
import { getLanguageIcon } from '../utils/languageIcon'
|
|
9
|
+
import { canParseOffthread, findPrefixOffthread } from '../workers/mermaidWorkerClient'
|
|
10
|
+
import { clampPreviewHeight, estimateMermaidPreviewHeight, getMermaidDiagramKind, parsePositiveNumber } from './shared/diagram-height'
|
|
11
|
+
import { copyTextToClipboard, downloadSvgMarkup } from './shared/rich-block-helpers'
|
|
12
|
+
import { getString } from './shared/node-helpers'
|
|
13
|
+
|
|
14
|
+
type MermaidTheme = 'light' | 'dark'
|
|
15
|
+
|
|
16
|
+
export let node: SvelteRenderableNode
|
|
17
|
+
export let context: SvelteRenderContext | undefined = undefined
|
|
18
|
+
export let maxHeight: string | null | undefined = '500px'
|
|
19
|
+
export let estimatedPreviewHeightPx: number | undefined = undefined
|
|
20
|
+
export let loading: boolean | undefined = undefined
|
|
21
|
+
export let isDark: boolean | undefined = undefined
|
|
22
|
+
export let workerTimeoutMs = 1400
|
|
23
|
+
export let parseTimeoutMs = 1800
|
|
24
|
+
export let renderTimeoutMs = 2500
|
|
25
|
+
export let fullRenderTimeoutMs = 4000
|
|
26
|
+
export let renderDebounceMs = 300
|
|
27
|
+
export let showHeader = true
|
|
28
|
+
export let showModeToggle = true
|
|
29
|
+
export let showCopyButton = true
|
|
30
|
+
export let showExportButton = true
|
|
31
|
+
export let showFullscreenButton = true
|
|
32
|
+
export let showCollapseButton = true
|
|
33
|
+
export let showZoomControls = true
|
|
34
|
+
export let isStrict = true
|
|
35
|
+
|
|
36
|
+
const { t } = useSafeI18n()
|
|
37
|
+
const mermaidIcon = getLanguageIcon('mermaid')
|
|
38
|
+
|
|
39
|
+
let mounted = false
|
|
40
|
+
let renderToken = 0
|
|
41
|
+
let lastRenderSignature = ''
|
|
42
|
+
let lastProgressiveMissSignature = ''
|
|
43
|
+
let lastRenderedCode = ''
|
|
44
|
+
let svgMarkup = ''
|
|
45
|
+
let svgCache: Partial<Record<MermaidTheme, string>> = {}
|
|
46
|
+
let renderError = ''
|
|
47
|
+
let rendering = false
|
|
48
|
+
let hasRenderedOnce = false
|
|
49
|
+
let copied = false
|
|
50
|
+
let collapsed = false
|
|
51
|
+
let showSource = false
|
|
52
|
+
let modalOpen = false
|
|
53
|
+
let zoom = 1
|
|
54
|
+
let renderTimer: ReturnType<typeof setTimeout> | null = null
|
|
55
|
+
let copyTimer: ReturnType<typeof setTimeout> | null = null
|
|
56
|
+
|
|
57
|
+
$: source = normalizeMermaidSource(getString((node as any)?.code))
|
|
58
|
+
$: nodeLoading = typeof (node as any)?.loading === 'boolean' ? Boolean((node as any)?.loading) : true
|
|
59
|
+
$: resolvedLoading = loading ?? nodeLoading
|
|
60
|
+
$: resolvedIsDark = isDark ?? context?.isDark ?? false
|
|
61
|
+
$: theme = (resolvedIsDark ? 'dark' : 'light') as MermaidTheme
|
|
62
|
+
$: final = context?.final ?? resolvedLoading === false
|
|
63
|
+
$: progressivePreview = resolvedLoading !== false || final === false
|
|
64
|
+
$: maxPreviewHeight = maxHeight === 'none' ? null : parsePositiveNumber(maxHeight)
|
|
65
|
+
$: previewHeight = clampPreviewHeight(
|
|
66
|
+
parsePositiveNumber(estimatedPreviewHeightPx) ?? estimateMermaidPreviewHeight(source),
|
|
67
|
+
undefined,
|
|
68
|
+
maxPreviewHeight ?? undefined,
|
|
69
|
+
)
|
|
70
|
+
$: previewStyle = [
|
|
71
|
+
`min-height: ${previewHeight}px`,
|
|
72
|
+
maxHeight && maxHeight !== 'none' ? `max-height: ${maxHeight}` : '',
|
|
73
|
+
`transform: scale(${zoom})`,
|
|
74
|
+
].filter(Boolean).join('; ')
|
|
75
|
+
$: shouldRender = !(resolvedLoading && !source.trim())
|
|
76
|
+
$: canUsePreview = Boolean(svgMarkup && !showSource)
|
|
77
|
+
|
|
78
|
+
onMount(() => {
|
|
79
|
+
mounted = true
|
|
80
|
+
scheduleRender(true)
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
afterUpdate(() => {
|
|
84
|
+
if (mounted)
|
|
85
|
+
scheduleRender()
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
onDestroy(() => {
|
|
89
|
+
mounted = false
|
|
90
|
+
renderToken += 1
|
|
91
|
+
clearRenderTimer()
|
|
92
|
+
if (copyTimer)
|
|
93
|
+
clearTimeout(copyTimer)
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
function clearRenderTimer() {
|
|
97
|
+
if (!renderTimer)
|
|
98
|
+
return
|
|
99
|
+
clearTimeout(renderTimer)
|
|
100
|
+
renderTimer = null
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function scheduleRender(force = false) {
|
|
104
|
+
if (!mounted || showSource || collapsed)
|
|
105
|
+
return
|
|
106
|
+
const signature = getRenderSignature()
|
|
107
|
+
if (signature === lastRenderSignature && rendering)
|
|
108
|
+
return
|
|
109
|
+
if (!force && signature === lastRenderSignature && (svgMarkup || renderError || lastProgressiveMissSignature === signature))
|
|
110
|
+
return
|
|
111
|
+
if (force)
|
|
112
|
+
clearRenderTimer()
|
|
113
|
+
if (renderTimer)
|
|
114
|
+
return
|
|
115
|
+
const delay = force || !progressivePreview ? 0 : Math.max(0, renderDebounceMs)
|
|
116
|
+
renderTimer = setTimeout(() => {
|
|
117
|
+
renderTimer = null
|
|
118
|
+
void renderMermaid(force)
|
|
119
|
+
}, delay)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function normalizeMermaidSource(value: string) {
|
|
123
|
+
return value
|
|
124
|
+
.replace(/\]::([^:])/g, ']:::$1')
|
|
125
|
+
.replace(/:::subgraphNode$/gm, '::subgraphNode')
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function applyMermaidThemeTo(value: string, nextTheme: MermaidTheme) {
|
|
129
|
+
const trimmed = value.trimStart()
|
|
130
|
+
if (trimmed.startsWith('%%{'))
|
|
131
|
+
return value
|
|
132
|
+
const themeValue = nextTheme === 'dark' ? 'dark' : 'default'
|
|
133
|
+
return `%%{init: {"theme": "${themeValue}"}}%%\n${value}`
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async function renderMermaid(force = false) {
|
|
137
|
+
if (!mounted || showSource || collapsed)
|
|
138
|
+
return
|
|
139
|
+
|
|
140
|
+
if (!source.trim()) {
|
|
141
|
+
svgMarkup = ''
|
|
142
|
+
renderError = ''
|
|
143
|
+
lastRenderedCode = ''
|
|
144
|
+
lastProgressiveMissSignature = ''
|
|
145
|
+
hasRenderedOnce = false
|
|
146
|
+
svgCache = {}
|
|
147
|
+
return
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const normalized = normalizeRenderedCode(source)
|
|
151
|
+
const signature = getRenderSignature()
|
|
152
|
+
if (signature === lastRenderSignature && rendering)
|
|
153
|
+
return
|
|
154
|
+
if (!force && signature === lastRenderSignature && (svgMarkup || renderError || lastProgressiveMissSignature === signature))
|
|
155
|
+
return
|
|
156
|
+
|
|
157
|
+
const token = ++renderToken
|
|
158
|
+
lastRenderSignature = signature
|
|
159
|
+
rendering = true
|
|
160
|
+
if (!progressivePreview)
|
|
161
|
+
renderError = ''
|
|
162
|
+
|
|
163
|
+
try {
|
|
164
|
+
const mermaid = await getMermaid({
|
|
165
|
+
startOnLoad: false,
|
|
166
|
+
securityLevel: isStrict ? 'strict' : 'loose',
|
|
167
|
+
suppressErrorRendering: true,
|
|
168
|
+
...(isStrict ? { flowchart: { htmlLabels: false } } : {}),
|
|
169
|
+
})
|
|
170
|
+
if (!mounted || token !== renderToken)
|
|
171
|
+
return
|
|
172
|
+
if (!mermaid)
|
|
173
|
+
throw new Error('Mermaid is not available.')
|
|
174
|
+
|
|
175
|
+
let renderSource = source
|
|
176
|
+
let fullRender = true
|
|
177
|
+
|
|
178
|
+
if (progressivePreview) {
|
|
179
|
+
if (hasRenderedOnce && normalized === lastRenderedCode && svgMarkup) {
|
|
180
|
+
renderError = ''
|
|
181
|
+
return
|
|
182
|
+
}
|
|
183
|
+
const parsed = await canParseOrPrefix(source, theme, mermaid)
|
|
184
|
+
if (!mounted || token !== renderToken)
|
|
185
|
+
return
|
|
186
|
+
if (parsed.fullOk) {
|
|
187
|
+
renderSource = source
|
|
188
|
+
}
|
|
189
|
+
else if (parsed.prefixOk && parsed.prefix && !hasRenderedOnce) {
|
|
190
|
+
renderSource = parsed.prefix
|
|
191
|
+
fullRender = false
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
renderError = ''
|
|
195
|
+
lastProgressiveMissSignature = signature
|
|
196
|
+
const cached = svgCache[theme]
|
|
197
|
+
if (cached)
|
|
198
|
+
svgMarkup = cached
|
|
199
|
+
return
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
await canParseMermaid(source, theme, mermaid)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const rendered = await withTimeout(
|
|
207
|
+
() => Promise.resolve(mermaid.render(`markstream-svelte-mermaid-${token}`, applyMermaidThemeTo(renderSource, theme))),
|
|
208
|
+
fullRender ? fullRenderTimeoutMs : renderTimeoutMs,
|
|
209
|
+
)
|
|
210
|
+
if (!mounted || token !== renderToken)
|
|
211
|
+
return
|
|
212
|
+
|
|
213
|
+
const rawSvg = typeof rendered === 'string' ? rendered : rendered?.svg
|
|
214
|
+
const safeSvg = isStrict ? toSafeSvgMarkup(rawSvg) : rawSvg
|
|
215
|
+
if (!safeSvg)
|
|
216
|
+
throw new Error('Mermaid rendered empty SVG.')
|
|
217
|
+
svgMarkup = safeSvg
|
|
218
|
+
renderError = ''
|
|
219
|
+
lastProgressiveMissSignature = ''
|
|
220
|
+
if (fullRender) {
|
|
221
|
+
hasRenderedOnce = true
|
|
222
|
+
lastRenderedCode = normalized
|
|
223
|
+
svgCache[theme] = safeSvg
|
|
224
|
+
}
|
|
225
|
+
rendered?.bindFunctions?.(document.createElement('div'))
|
|
226
|
+
}
|
|
227
|
+
catch (error) {
|
|
228
|
+
if (token === renderToken) {
|
|
229
|
+
if (progressivePreview) {
|
|
230
|
+
renderError = ''
|
|
231
|
+
lastProgressiveMissSignature = signature
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
svgMarkup = ''
|
|
235
|
+
renderError = error instanceof Error ? error.message : String(error)
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
finally {
|
|
240
|
+
if (token === renderToken)
|
|
241
|
+
rendering = false
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
async function canParseMermaid(value: string, nextTheme: MermaidTheme, mermaid: any) {
|
|
246
|
+
try {
|
|
247
|
+
if (await canParseOffthread(value, nextTheme, workerTimeoutMs))
|
|
248
|
+
return true
|
|
249
|
+
}
|
|
250
|
+
catch {}
|
|
251
|
+
|
|
252
|
+
const themedSource = applyMermaidThemeTo(value, nextTheme)
|
|
253
|
+
if (typeof mermaid?.parse === 'function') {
|
|
254
|
+
await withTimeout(() => Promise.resolve(mermaid.parse(themedSource)), parseTimeoutMs)
|
|
255
|
+
return true
|
|
256
|
+
}
|
|
257
|
+
await withTimeout(() => Promise.resolve(mermaid.render(`markstream-svelte-mermaid-parse-${renderToken}`, themedSource)), parseTimeoutMs)
|
|
258
|
+
return true
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
async function canParseOrPrefix(value: string, nextTheme: MermaidTheme, mermaid: any) {
|
|
262
|
+
if (getMermaidDiagramKind(value) === 'gantt') {
|
|
263
|
+
const prefix = getSafeMermaidPrefixCandidate(value)
|
|
264
|
+
if (!prefix.trim())
|
|
265
|
+
return { fullOk: false, prefixOk: false }
|
|
266
|
+
try {
|
|
267
|
+
await canParseMermaid(prefix, nextTheme, mermaid)
|
|
268
|
+
return prefix === value
|
|
269
|
+
? { fullOk: true, prefixOk: false }
|
|
270
|
+
: { fullOk: false, prefixOk: true, prefix }
|
|
271
|
+
}
|
|
272
|
+
catch {
|
|
273
|
+
return { fullOk: false, prefixOk: false }
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
try {
|
|
278
|
+
await canParseMermaid(value, nextTheme, mermaid)
|
|
279
|
+
return { fullOk: true, prefixOk: false }
|
|
280
|
+
}
|
|
281
|
+
catch {
|
|
282
|
+
// Try a renderable prefix below.
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
let prefix = getSafeMermaidPrefixCandidate(value)
|
|
286
|
+
if (!prefix.trim() || prefix === value)
|
|
287
|
+
return { fullOk: false, prefixOk: false }
|
|
288
|
+
|
|
289
|
+
try {
|
|
290
|
+
const workerPrefix = await findPrefixOffthread(value, nextTheme, workerTimeoutMs)
|
|
291
|
+
if (workerPrefix?.trim())
|
|
292
|
+
prefix = workerPrefix
|
|
293
|
+
}
|
|
294
|
+
catch {
|
|
295
|
+
// Keep the local prefix.
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
try {
|
|
299
|
+
await canParseMermaid(prefix, nextTheme, mermaid)
|
|
300
|
+
return { fullOk: false, prefixOk: true, prefix }
|
|
301
|
+
}
|
|
302
|
+
catch {
|
|
303
|
+
return { fullOk: false, prefixOk: false }
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function isGanttTaskLine(rawLine: string) {
|
|
308
|
+
const line = rawLine.trim()
|
|
309
|
+
if (!line || line.startsWith('%%'))
|
|
310
|
+
return false
|
|
311
|
+
if (/^(?:gantt|title|dateformat|axisformat|tickinterval|excludes|section|todaymarker|topaxis|weekday|weekend|acctitle|accdescr|accdescrmultiline)\b/i.test(line))
|
|
312
|
+
return false
|
|
313
|
+
return line.includes(':')
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function getSafeGanttPreviewCandidate(value: string) {
|
|
317
|
+
const lines = value.split(/\r?\n/)
|
|
318
|
+
if (!/\r?\n$/.test(value) && lines.length > 0)
|
|
319
|
+
lines.pop()
|
|
320
|
+
while (lines.length > 0) {
|
|
321
|
+
const last = lines[lines.length - 1]?.trim()
|
|
322
|
+
if (!last || last.startsWith('%%')) {
|
|
323
|
+
lines.pop()
|
|
324
|
+
continue
|
|
325
|
+
}
|
|
326
|
+
if (isGanttTaskLine(last))
|
|
327
|
+
break
|
|
328
|
+
lines.pop()
|
|
329
|
+
}
|
|
330
|
+
return lines.some(isGanttTaskLine) ? lines.join('\n') : ''
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function getSafeMermaidPrefixCandidate(value: string) {
|
|
334
|
+
if (getMermaidDiagramKind(value) === 'gantt')
|
|
335
|
+
return getSafeGanttPreviewCandidate(value)
|
|
336
|
+
const lines = value.split('\n')
|
|
337
|
+
while (lines.length > 0) {
|
|
338
|
+
const last = (lines[lines.length - 1] || '').trimEnd()
|
|
339
|
+
if (!last) {
|
|
340
|
+
lines.pop()
|
|
341
|
+
continue
|
|
342
|
+
}
|
|
343
|
+
const dangling = /^[-=~>|<\s]+$/.test(last.trim())
|
|
344
|
+
|| /(?:--|==|~~|->|<-|-\||-\)|-x|o-|\|-|\.-)\s*$/.test(last)
|
|
345
|
+
|| /[-|><]$/.test(last)
|
|
346
|
+
|| /(?:graph|flowchart|sequenceDiagram|classDiagram|stateDiagram|erDiagram|gantt)\s*$/i.test(last)
|
|
347
|
+
if (!dangling)
|
|
348
|
+
break
|
|
349
|
+
lines.pop()
|
|
350
|
+
}
|
|
351
|
+
return lines.join('\n').trim() || ''
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
function normalizeRenderedCode(value: string) {
|
|
355
|
+
return value.replace(/\s+/g, '')
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
function getRenderSignature() {
|
|
359
|
+
return `${source}\n${theme}\n${isStrict}\n${final}\n${progressivePreview}`
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
function withTimeout<T>(run: () => Promise<T>, timeoutMs: number) {
|
|
363
|
+
if (!timeoutMs || timeoutMs <= 0)
|
|
364
|
+
return run()
|
|
365
|
+
return new Promise<T>((resolve, reject) => {
|
|
366
|
+
const timer = setTimeout(() => reject(new Error('Operation timed out')), timeoutMs)
|
|
367
|
+
run().then((value) => {
|
|
368
|
+
clearTimeout(timer)
|
|
369
|
+
resolve(value)
|
|
370
|
+
}).catch((error) => {
|
|
371
|
+
clearTimeout(timer)
|
|
372
|
+
reject(error)
|
|
373
|
+
})
|
|
374
|
+
})
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
async function copy() {
|
|
378
|
+
await copyTextToClipboard(source)
|
|
379
|
+
context?.events?.onCopy?.(source)
|
|
380
|
+
copied = true
|
|
381
|
+
if (copyTimer)
|
|
382
|
+
clearTimeout(copyTimer)
|
|
383
|
+
copyTimer = setTimeout(() => {
|
|
384
|
+
copied = false
|
|
385
|
+
}, 1000)
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
function exportSvg() {
|
|
389
|
+
if (svgMarkup)
|
|
390
|
+
downloadSvgMarkup(svgMarkup, `mermaid-diagram-${Date.now()}.svg`)
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
function switchMode(mode: 'preview' | 'source') {
|
|
394
|
+
showSource = mode === 'source'
|
|
395
|
+
if (!showSource)
|
|
396
|
+
void renderMermaid()
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
function zoomIn() {
|
|
400
|
+
zoom = Math.min(3, Math.round((zoom + 0.1) * 10) / 10)
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
function zoomOut() {
|
|
404
|
+
zoom = Math.max(0.5, Math.round((zoom - 0.1) * 10) / 10)
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function showButtonTooltip(event: MouseEvent | FocusEvent, text: string, placement: TooltipPlacement = 'top') {
|
|
408
|
+
const target = event.currentTarget as HTMLElement | null
|
|
409
|
+
if (!target || (target instanceof HTMLButtonElement && target.disabled))
|
|
410
|
+
return
|
|
411
|
+
showTooltipForAnchor(target, text, placement, false, undefined, resolvedIsDark)
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
function showCopyTooltip(event: MouseEvent | FocusEvent) {
|
|
415
|
+
showButtonTooltip(event, copied ? (t('common.copied') || 'Copied') : (t('common.copy') || 'Copy'))
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
function portal(node: HTMLElement) {
|
|
419
|
+
document.body.appendChild(node)
|
|
420
|
+
return {
|
|
421
|
+
destroy() {
|
|
422
|
+
node.remove()
|
|
423
|
+
},
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
function closeModal() {
|
|
428
|
+
modalOpen = false
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
function onModalOverlayClick(event: MouseEvent) {
|
|
432
|
+
if (event.target === event.currentTarget)
|
|
433
|
+
closeModal()
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
function onModalKeydown(event: KeyboardEvent) {
|
|
437
|
+
if (event.key === 'Escape')
|
|
438
|
+
closeModal()
|
|
439
|
+
}
|
|
440
|
+
</script>
|
|
441
|
+
|
|
442
|
+
{#if shouldRender}
|
|
443
|
+
<div
|
|
444
|
+
class:dark={resolvedIsDark}
|
|
445
|
+
class:is-rendering={resolvedLoading || rendering}
|
|
446
|
+
class="mermaid-block"
|
|
447
|
+
data-markstream-mermaid="1"
|
|
448
|
+
data-markstream-mode={showSource ? 'source' : canUsePreview ? 'preview' : 'fallback'}
|
|
449
|
+
>
|
|
450
|
+
{#if showHeader}
|
|
451
|
+
<div class="mermaid-header">
|
|
452
|
+
<div class="mermaid-header__title">
|
|
453
|
+
<span class="icon-slot action-icon" aria-hidden="true">{@html mermaidIcon}</span>
|
|
454
|
+
<span class="mermaid-title__text">Mermaid</span>
|
|
455
|
+
</div>
|
|
456
|
+
{#if showModeToggle}
|
|
457
|
+
<div class="mermaid-toggle">
|
|
458
|
+
<button type="button" class:mermaid-toggle-btn--active={!showSource} class="mermaid-toggle-btn" onblur={() => hideTooltip()} onclick={() => switchMode('preview')} onfocus={(event) => showButtonTooltip(event, t('common.preview') || 'Preview')} onmouseleave={() => hideTooltip()} onmouseenter={(event) => showButtonTooltip(event, t('common.preview') || 'Preview')}>
|
|
459
|
+
<span class="mermaid-action-content">
|
|
460
|
+
<svg aria-hidden="true" role="img" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M2.062 12.348a1 1 0 0 1 0-.696a10.75 10.75 0 0 1 19.876 0a1 1 0 0 1 0 .696a10.75 10.75 0 0 1-19.876 0"/><circle cx="12" cy="12" r="3"/></g></svg>
|
|
461
|
+
<span>{t('common.preview')}</span>
|
|
462
|
+
</span>
|
|
463
|
+
</button>
|
|
464
|
+
<button type="button" class:mermaid-toggle-btn--active={showSource} class="mermaid-toggle-btn" onblur={() => hideTooltip()} onclick={() => switchMode('source')} onfocus={(event) => showButtonTooltip(event, t('common.source') || 'Source')} onmouseleave={() => hideTooltip()} onmouseenter={(event) => showButtonTooltip(event, t('common.source') || 'Source')}>
|
|
465
|
+
<span class="mermaid-action-content">
|
|
466
|
+
<svg aria-hidden="true" role="img" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m16 18l6-6l-6-6M8 6l-6 6l6 6"/></svg>
|
|
467
|
+
<span>{t('common.source')}</span>
|
|
468
|
+
</span>
|
|
469
|
+
</button>
|
|
470
|
+
</div>
|
|
471
|
+
{/if}
|
|
472
|
+
<div class="mermaid-actions">
|
|
473
|
+
{#if showCollapseButton}
|
|
474
|
+
<button type="button" class="mermaid-btn mermaid-action-btn mermaid-btn--icon" aria-pressed={collapsed} aria-label={collapsed ? t('common.expand') : t('common.collapse')} onblur={() => hideTooltip()} onclick={() => (collapsed = !collapsed)} onfocus={(event) => showButtonTooltip(event, collapsed ? (t('common.expand') || 'Expand') : (t('common.collapse') || 'Collapse'))} onmouseleave={() => hideTooltip()} onmouseenter={(event) => showButtonTooltip(event, collapsed ? (t('common.expand') || 'Expand') : (t('common.collapse') || 'Collapse'))}>
|
|
475
|
+
<svg style:rotate={collapsed ? '0deg' : '90deg'} viewBox="0 0 24 24" aria-hidden="true"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m9 18l6-6l-6-6" /></svg>
|
|
476
|
+
</button>
|
|
477
|
+
{/if}
|
|
478
|
+
{#if showCopyButton}
|
|
479
|
+
<button type="button" class="mermaid-btn mermaid-action-btn mermaid-btn--icon" aria-label={copied ? t('common.copied') : t('common.copy')} onblur={() => hideTooltip()} onclick={copy} onfocus={showCopyTooltip} onmouseleave={() => hideTooltip()} onmouseenter={showCopyTooltip}>
|
|
480
|
+
{#if copied}
|
|
481
|
+
<svg aria-hidden="true" role="img" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 6L9 17l-5-5"/></svg>
|
|
482
|
+
{:else}
|
|
483
|
+
<svg aria-hidden="true" role="img" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></g></svg>
|
|
484
|
+
{/if}
|
|
485
|
+
</button>
|
|
486
|
+
{/if}
|
|
487
|
+
{#if showExportButton}
|
|
488
|
+
<button type="button" class="mermaid-btn mermaid-action-btn mermaid-btn--icon" aria-label={t('common.export')} disabled={!svgMarkup || showSource || collapsed} onblur={() => hideTooltip()} onclick={exportSvg} onfocus={(event) => showButtonTooltip(event, t('common.export') || 'Export')} onmouseleave={() => hideTooltip()} onmouseenter={(event) => showButtonTooltip(event, t('common.export') || 'Export')}>
|
|
489
|
+
<svg aria-hidden="true" role="img" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M12 15V3m9 12v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m7 10l5 5l5-5"/></g></svg>
|
|
490
|
+
</button>
|
|
491
|
+
{/if}
|
|
492
|
+
{#if showFullscreenButton}
|
|
493
|
+
<button type="button" class="mermaid-btn mermaid-action-btn mermaid-btn--icon" aria-label={t('common.open')} disabled={!svgMarkup || showSource || collapsed} onblur={() => hideTooltip()} onclick={() => (modalOpen = true)} onfocus={(event) => showButtonTooltip(event, t('common.open') || 'Open')} onmouseleave={() => hideTooltip()} onmouseenter={(event) => showButtonTooltip(event, t('common.open') || 'Open')}>
|
|
494
|
+
<svg aria-hidden="true" role="img" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 3h6v6m0-6l-7 7M3 21l7-7m-1 7H3v-6"/></svg>
|
|
495
|
+
</button>
|
|
496
|
+
{/if}
|
|
497
|
+
</div>
|
|
498
|
+
</div>
|
|
499
|
+
{/if}
|
|
500
|
+
|
|
501
|
+
{#if !collapsed}
|
|
502
|
+
<div class="mermaid-body">
|
|
503
|
+
{#if showSource}
|
|
504
|
+
<pre class="mermaid-source"><code>{source}</code></pre>
|
|
505
|
+
{:else}
|
|
506
|
+
{#if showZoomControls}
|
|
507
|
+
<div class="markstream-svelte-zoom-controls">
|
|
508
|
+
<button type="button" class="mermaid-btn mermaid-action-btn mermaid-btn--icon" aria-label={t('common.zoomIn')} onblur={() => hideTooltip()} onclick={zoomIn} onfocus={(event) => showButtonTooltip(event, t('common.zoomIn') || 'Zoom in')} onmouseleave={() => hideTooltip()} onmouseenter={(event) => showButtonTooltip(event, t('common.zoomIn') || 'Zoom in')}>
|
|
509
|
+
<svg aria-hidden="true" role="img" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="m21 21l-4.35-4.35M11 8v6m-3-3h6"/></g></svg>
|
|
510
|
+
</button>
|
|
511
|
+
<button type="button" class="mermaid-btn mermaid-action-btn mermaid-btn--icon" aria-label={t('common.zoomOut')} onblur={() => hideTooltip()} onclick={zoomOut} onfocus={(event) => showButtonTooltip(event, t('common.zoomOut') || 'Zoom out')} onmouseleave={() => hideTooltip()} onmouseenter={(event) => showButtonTooltip(event, t('common.zoomOut') || 'Zoom out')}>
|
|
512
|
+
<svg aria-hidden="true" role="img" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="m21 21l-4.35-4.35M8 11h6"/></g></svg>
|
|
513
|
+
</button>
|
|
514
|
+
<button type="button" class="mermaid-btn mermaid-action-btn mermaid-zoom-reset" aria-label={t('common.resetZoom')} onblur={() => hideTooltip()} onclick={() => (zoom = 1)} onfocus={(event) => showButtonTooltip(event, t('common.resetZoom') || 'Reset zoom')} onmouseleave={() => hideTooltip()} onmouseenter={(event) => showButtonTooltip(event, t('common.resetZoom') || 'Reset zoom')}>{Math.round(zoom * 100)}%</button>
|
|
515
|
+
</div>
|
|
516
|
+
{/if}
|
|
517
|
+
<div class="mermaid-preview markstream-svelte-mermaid" style={previewStyle}>
|
|
518
|
+
{#if svgMarkup}
|
|
519
|
+
{@html svgMarkup}
|
|
520
|
+
{:else if renderError}
|
|
521
|
+
<pre class="mermaid-source"><code>{source}</code></pre>
|
|
522
|
+
{:else}
|
|
523
|
+
<div class="mermaid-loading"><span class="mermaid-spinner"></span> {t('common.preview')}</div>
|
|
524
|
+
{/if}
|
|
525
|
+
</div>
|
|
526
|
+
{#if renderError}
|
|
527
|
+
<div class="mermaid-error">{renderError}</div>
|
|
528
|
+
{/if}
|
|
529
|
+
{/if}
|
|
530
|
+
</div>
|
|
531
|
+
{/if}
|
|
532
|
+
|
|
533
|
+
{#if modalOpen}
|
|
534
|
+
<div use:portal class:dark={resolvedIsDark} class="markstream-svelte markstream-svelte-modal-root">
|
|
535
|
+
<div class="mermaid-modal-overlay" role="dialog" aria-modal="true" tabindex="-1" onclick={onModalOverlayClick} onkeydown={onModalKeydown}>
|
|
536
|
+
<div class="mermaid-modal-panel">
|
|
537
|
+
<div class="mermaid-modal-controls">
|
|
538
|
+
<button type="button" class="mermaid-btn mermaid-action-btn mermaid-btn--icon" aria-label={t('common.zoomIn')} onclick={zoomIn}>
|
|
539
|
+
<svg aria-hidden="true" role="img" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="m21 21l-4.35-4.35M11 8v6m-3-3h6"/></g></svg>
|
|
540
|
+
</button>
|
|
541
|
+
<button type="button" class="mermaid-btn mermaid-action-btn mermaid-btn--icon" aria-label={t('common.zoomOut')} onclick={zoomOut}>
|
|
542
|
+
<svg aria-hidden="true" role="img" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="m21 21l-4.35-4.35M8 11h6"/></g></svg>
|
|
543
|
+
</button>
|
|
544
|
+
<button type="button" class="mermaid-btn mermaid-action-btn mermaid-zoom-reset" aria-label={t('common.resetZoom')} onclick={() => (zoom = 1)}>{Math.round(zoom * 100)}%</button>
|
|
545
|
+
<button type="button" class="mermaid-btn mermaid-action-btn mermaid-btn--icon" aria-label={t('common.close')} onclick={closeModal}>
|
|
546
|
+
<svg aria-hidden="true" role="img" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M18 6L6 18M6 6l12 12"/></svg>
|
|
547
|
+
</button>
|
|
548
|
+
</div>
|
|
549
|
+
<div class="mermaid-modal-body">
|
|
550
|
+
<div class="mermaid-modal-content markstream-svelte-mermaid" style={`transform: scale(${zoom});`}>{@html svgMarkup}</div>
|
|
551
|
+
</div>
|
|
552
|
+
</div>
|
|
553
|
+
</div>
|
|
554
|
+
</div>
|
|
555
|
+
{/if}
|
|
556
|
+
</div>
|
|
557
|
+
{/if}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { SvelteRenderableNode, SvelteRenderContext } from './shared/node-helpers';
|
|
2
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
3
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
4
|
+
$$bindings?: Bindings;
|
|
5
|
+
} & Exports;
|
|
6
|
+
(internal: unknown, props: Props & {
|
|
7
|
+
$$events?: Events;
|
|
8
|
+
$$slots?: Slots;
|
|
9
|
+
}): Exports & {
|
|
10
|
+
$set?: any;
|
|
11
|
+
$on?: any;
|
|
12
|
+
};
|
|
13
|
+
z_$$bindings?: Bindings;
|
|
14
|
+
}
|
|
15
|
+
declare const MermaidBlockNode: $$__sveltets_2_IsomorphicComponent<{
|
|
16
|
+
node: SvelteRenderableNode;
|
|
17
|
+
context?: SvelteRenderContext | undefined;
|
|
18
|
+
maxHeight?: string | null | undefined;
|
|
19
|
+
estimatedPreviewHeightPx?: number | undefined;
|
|
20
|
+
loading?: boolean | undefined;
|
|
21
|
+
isDark?: boolean | undefined;
|
|
22
|
+
workerTimeoutMs?: number;
|
|
23
|
+
parseTimeoutMs?: number;
|
|
24
|
+
renderTimeoutMs?: number;
|
|
25
|
+
fullRenderTimeoutMs?: number;
|
|
26
|
+
renderDebounceMs?: number;
|
|
27
|
+
showHeader?: boolean;
|
|
28
|
+
showModeToggle?: boolean;
|
|
29
|
+
showCopyButton?: boolean;
|
|
30
|
+
showExportButton?: boolean;
|
|
31
|
+
showFullscreenButton?: boolean;
|
|
32
|
+
showCollapseButton?: boolean;
|
|
33
|
+
showZoomControls?: boolean;
|
|
34
|
+
isStrict?: boolean;
|
|
35
|
+
}, {
|
|
36
|
+
[evt: string]: CustomEvent<any>;
|
|
37
|
+
}, {}, {}, string>;
|
|
38
|
+
type MermaidBlockNode = InstanceType<typeof MermaidBlockNode>;
|
|
39
|
+
export default MermaidBlockNode;
|
|
40
|
+
//# sourceMappingURL=MermaidBlockNode.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MermaidBlockNode.svelte.d.ts","sourceRoot":"","sources":["../../src/components/MermaidBlockNode.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAsjBtF,UAAU,kCAAkC,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,OAAO,GAAG,EAAE,EAAE,QAAQ,GAAG,MAAM;IACpM,KAAK,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,KAAK,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC;IACjK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,GAAG;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,CAAA;KAAC,GAAG,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IAC9G,YAAY,CAAC,EAAE,QAAQ,CAAC;CAC3B;AAKD,QAAA,MAAM,gBAAgB;UAV2lB,oBAAoB;cAAY,mBAAmB,GAAG,SAAS;gBAAc,MAAM,GAAG,IAAI,GAAG,SAAS;+BAA6B,MAAM,GAAG,SAAS;cAAY,OAAO,GAAG,SAAS;aAAW,OAAO,GAAG,SAAS;;;;;;;;;;;;;;;;kBAU9tB,CAAC;AACpF,KAAK,gBAAgB,GAAG,YAAY,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAChE,eAAe,gBAAgB,CAAC"}
|