markstream-svelte 2.0.14 → 2.0.16
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/dist/components/CodeBlockNode.svelte +63 -11
- package/dist/components/D2BlockNode.svelte +2 -0
- package/dist/components/FootnoteAnchorNode.svelte +2 -1
- package/dist/components/FootnoteReferenceNode.svelte +2 -1
- package/dist/components/MermaidBlockNode.svelte +3 -2
- package/dist/components/NodeRenderer.svelte +7 -2
- package/dist/enhanceRenderedHtml.js +12 -4
- package/dist/index.css +5 -3
- package/dist/index.px.css +5 -3
- package/dist/index.tailwind.css +5 -3
- package/dist/utils/d2RenderSalt.d.ts +1 -0
- package/dist/utils/d2RenderSalt.js +13 -0
- package/dist/utils/footnoteTarget.d.ts +1 -0
- package/dist/utils/footnoteTarget.js +21 -0
- package/dist/utils/mermaidRenderId.d.ts +1 -0
- package/dist/utils/mermaidRenderId.js +13 -0
- package/package.json +4 -3
|
@@ -137,6 +137,8 @@
|
|
|
137
137
|
let lifecycleId = $state(0)
|
|
138
138
|
let heightSyncRaf: number | null = $state(null)
|
|
139
139
|
let heightSyncDisposables: Array<{ dispose?: () => void } | (() => void)> = $state([])
|
|
140
|
+
let editorSurfaceResizeObserver: ResizeObserver | null = $state(null)
|
|
141
|
+
let editorSurfaceResizeTarget: HTMLElement | null = $state(null)
|
|
140
142
|
let lastLayoutWidth: number | null = $state(null)
|
|
141
143
|
let lastLayoutHeight: number | null = $state(null)
|
|
142
144
|
let lastThemeRequest = $state('')
|
|
@@ -706,6 +708,10 @@ ${configuredUnsafeCSS}`.trim(),
|
|
|
706
708
|
function nextAnimationFrame() {
|
|
707
709
|
if (typeof window === 'undefined' || typeof window.requestAnimationFrame !== 'function')
|
|
708
710
|
return Promise.resolve()
|
|
711
|
+
// Animation frames never run in hidden tabs; fall back to a timer so the
|
|
712
|
+
// editor handoff loop cannot stall indefinitely while the page is hidden.
|
|
713
|
+
if (typeof document !== 'undefined' && document.visibilityState === 'hidden')
|
|
714
|
+
return new Promise<void>(resolve => setTimeout(() => resolve(), 0))
|
|
709
715
|
return new Promise<void>(resolve => window.requestAnimationFrame(() => resolve()))
|
|
710
716
|
}
|
|
711
717
|
|
|
@@ -843,6 +849,39 @@ ${configuredUnsafeCSS}`.trim(),
|
|
|
843
849
|
catch {}
|
|
844
850
|
}
|
|
845
851
|
|
|
852
|
+
function bindEditorSurfaceResizeSync() {
|
|
853
|
+
if (typeof ResizeObserver === 'undefined' || !editorHost)
|
|
854
|
+
return
|
|
855
|
+
const surface = getVisualEditorSurface()
|
|
856
|
+
if (editorSurfaceResizeObserver && surface === editorSurfaceResizeTarget)
|
|
857
|
+
return
|
|
858
|
+
unbindEditorSurfaceResizeSync()
|
|
859
|
+
if (!surface)
|
|
860
|
+
return
|
|
861
|
+
// The diff surface re-renders at a different height when unchanged regions
|
|
862
|
+
// collapse/expand and when a settled stream replaces the partial layout.
|
|
863
|
+
// Those changes do not always surface through the editor events bound
|
|
864
|
+
// above, so observe the rendered surface and re-sync the host height when
|
|
865
|
+
// the rendered height no longer matches the host.
|
|
866
|
+
editorSurfaceResizeObserver = new ResizeObserver(() => {
|
|
867
|
+
if (!editorHost || collapsed)
|
|
868
|
+
return
|
|
869
|
+
const renderedHeight = measureRenderedDiffHeight(editorHost)
|
|
870
|
+
const hostHeight = Math.ceil(editorHost.getBoundingClientRect().height || 0)
|
|
871
|
+
if (renderedHeight == null || Math.abs(renderedHeight - hostHeight) <= 1)
|
|
872
|
+
return
|
|
873
|
+
scheduleEditorHeightSync()
|
|
874
|
+
})
|
|
875
|
+
editorSurfaceResizeObserver.observe(surface)
|
|
876
|
+
editorSurfaceResizeTarget = surface
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
function unbindEditorSurfaceResizeSync() {
|
|
880
|
+
editorSurfaceResizeObserver?.disconnect()
|
|
881
|
+
editorSurfaceResizeObserver = null
|
|
882
|
+
editorSurfaceResizeTarget = null
|
|
883
|
+
}
|
|
884
|
+
|
|
846
885
|
function bindEditorHeightSync() {
|
|
847
886
|
clearEditorHeightSyncBindings()
|
|
848
887
|
const bind = (source: any, eventName: 'onDidContentSizeChange' | 'onDidLayoutChange') => {
|
|
@@ -871,6 +910,7 @@ ${configuredUnsafeCSS}`.trim(),
|
|
|
871
910
|
bind(modifiedEditor, 'onDidContentSizeChange')
|
|
872
911
|
bind(originalEditor, 'onDidLayoutChange')
|
|
873
912
|
bind(modifiedEditor, 'onDidLayoutChange')
|
|
913
|
+
bindEditorSurfaceResizeSync()
|
|
874
914
|
return
|
|
875
915
|
}
|
|
876
916
|
|
|
@@ -880,6 +920,7 @@ ${configuredUnsafeCSS}`.trim(),
|
|
|
880
920
|
}
|
|
881
921
|
|
|
882
922
|
function clearEditorHeightSyncBindings() {
|
|
923
|
+
unbindEditorSurfaceResizeSync()
|
|
883
924
|
for (const disposable of heightSyncDisposables) {
|
|
884
925
|
try {
|
|
885
926
|
if (typeof disposable === 'function')
|
|
@@ -911,22 +952,33 @@ ${configuredUnsafeCSS}`.trim(),
|
|
|
911
952
|
editorHost.style.height = `${nextHeight}px`
|
|
912
953
|
editorHost.style.minHeight = `${nextHeight}px`
|
|
913
954
|
editorHost.style.maxHeight = expanded || !Number.isFinite(maxHeight) ? 'none' : `${Math.ceil(maxHeight)}px`
|
|
914
|
-
editorHost.style.overflow =
|
|
955
|
+
editorHost.style.overflow = contentHeight > nextHeight ? 'auto' : 'hidden'
|
|
915
956
|
layoutEditor(nextHeight)
|
|
957
|
+
if (diff)
|
|
958
|
+
bindEditorSurfaceResizeSync()
|
|
916
959
|
}
|
|
917
960
|
|
|
918
961
|
function getEditorHostMinHeight() {
|
|
919
962
|
if (!editorHost || typeof window === 'undefined')
|
|
920
963
|
return 0
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
964
|
+
// A consumer-configured min-height on the body element is a real floor.
|
|
965
|
+
const parentMinHeight = window.getComputedStyle(editorHost.parentElement || editorHost).minHeight
|
|
966
|
+
const parsedParentMinHeight = Number.parseFloat(parentMinHeight)
|
|
967
|
+
if (Number.isFinite(parsedParentMinHeight) && parsedParentMinHeight > 0)
|
|
968
|
+
return Math.ceil(parsedParentMinHeight)
|
|
969
|
+
// `syncEditorHostHeight` writes the host's inline min-height, so reading the
|
|
970
|
+
// computed value back would pin the host at its largest historical height
|
|
971
|
+
// and stop the container from shrinking when the diff surface collapses
|
|
972
|
+
// unchanged regions. Temporarily drop the inline value so the computed
|
|
973
|
+
// min-height reflects only a consumer/CSS-configured floor.
|
|
974
|
+
const inlineMinHeight = editorHost.style.minHeight
|
|
975
|
+
if (inlineMinHeight)
|
|
976
|
+
editorHost.style.minHeight = ''
|
|
977
|
+
const configuredMinHeight = Number.parseFloat(window.getComputedStyle(editorHost).minHeight)
|
|
978
|
+
if (inlineMinHeight)
|
|
979
|
+
editorHost.style.minHeight = inlineMinHeight
|
|
980
|
+
if (Number.isFinite(configuredMinHeight) && configuredMinHeight > 0)
|
|
981
|
+
return Math.ceil(configuredMinHeight)
|
|
930
982
|
return 0
|
|
931
983
|
}
|
|
932
984
|
|
|
@@ -1101,7 +1153,7 @@ ${configuredUnsafeCSS}`.trim(),
|
|
|
1101
1153
|
{#if !shouldDelayEditor}
|
|
1102
1154
|
<div bind:this={editorHost} class:is-hidden={!editorRevealed} class="code-editor-container"></div>
|
|
1103
1155
|
{/if}
|
|
1104
|
-
<div class:is-
|
|
1156
|
+
<div class:is-retired={fallbackRetired} class="code-editor-fallback-surface">
|
|
1105
1157
|
<PreCodeNode
|
|
1106
1158
|
class="code-pre-fallback"
|
|
1107
1159
|
enhanceable={false}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { getD2 } from '../optional/d2'
|
|
6
6
|
import { extractRenderedSvg, toSafeSvgMarkup } from '../sanitizeSvg'
|
|
7
7
|
import { hideTooltip, showTooltipForAnchor } from '../tooltip/singletonTooltip'
|
|
8
|
+
import { createD2RenderSalt } from '../utils/d2RenderSalt'
|
|
8
9
|
import { copyTextToClipboard, downloadSvgMarkup } from './shared/rich-block-helpers'
|
|
9
10
|
import { getString } from './shared/node-helpers'
|
|
10
11
|
|
|
@@ -153,6 +154,7 @@
|
|
|
153
154
|
}
|
|
154
155
|
}
|
|
155
156
|
|
|
157
|
+
renderOptions.salt = renderOptions.salt ?? createD2RenderSalt()
|
|
156
158
|
const rendered = await instance.render(diagram, renderOptions)
|
|
157
159
|
if (!mounted || token !== renderToken)
|
|
158
160
|
return
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { SvelteRenderableNode } from './shared/node-helpers'
|
|
3
3
|
import { getString } from './shared/node-helpers'
|
|
4
|
+
import { findFootnoteElement } from '../utils/footnoteTarget'
|
|
4
5
|
|
|
5
6
|
interface Props {
|
|
6
7
|
node: SvelteRenderableNode
|
|
@@ -15,7 +16,7 @@
|
|
|
15
16
|
event.preventDefault()
|
|
16
17
|
if (typeof document === 'undefined' || !id)
|
|
17
18
|
return
|
|
18
|
-
const target =
|
|
19
|
+
const target = findFootnoteElement(event.currentTarget, `fnref-${id}`)
|
|
19
20
|
target?.scrollIntoView({ behavior: 'smooth', block: 'center' })
|
|
20
21
|
}
|
|
21
22
|
</script>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { SvelteRenderableNode } from './shared/node-helpers'
|
|
3
3
|
import { getString } from './shared/node-helpers'
|
|
4
|
+
import { findFootnoteElement } from '../utils/footnoteTarget'
|
|
4
5
|
|
|
5
6
|
interface Props {
|
|
6
7
|
node: SvelteRenderableNode
|
|
@@ -16,7 +17,7 @@
|
|
|
16
17
|
event.preventDefault()
|
|
17
18
|
if (typeof document === 'undefined' || !id)
|
|
18
19
|
return
|
|
19
|
-
const target =
|
|
20
|
+
const target = findFootnoteElement(event.currentTarget, `fnref--${id}`)
|
|
20
21
|
target?.scrollIntoView({ behavior: 'smooth', block: 'start' })
|
|
21
22
|
}
|
|
22
23
|
</script>
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import { getMermaid } from '../optional/mermaid'
|
|
8
8
|
import { hideTooltip, showTooltipForAnchor, type TooltipPlacement } from '../tooltip/singletonTooltip'
|
|
9
9
|
import { getLanguageIcon } from '../utils/languageIcon'
|
|
10
|
+
import { createMermaidRenderId } from '../utils/mermaidRenderId'
|
|
10
11
|
import { canParseOffthread, findPrefixOffthread } from '../workers/mermaidWorkerClient'
|
|
11
12
|
import { clampPreviewHeight, estimateMermaidPreviewHeight, getMermaidDiagramKind, MERMAID_PREVIEW_MIN_HEIGHT, parsePositiveNumber, resolveDiagramMinPreviewHeight } from './shared/diagram-height'
|
|
12
13
|
import { copyTextToClipboard, downloadSvgMarkup } from './shared/rich-block-helpers'
|
|
@@ -257,7 +258,7 @@
|
|
|
257
258
|
}
|
|
258
259
|
|
|
259
260
|
const rendered = await withTimeout(
|
|
260
|
-
() => Promise.resolve(mermaid.render(
|
|
261
|
+
() => Promise.resolve(mermaid.render(createMermaidRenderId(), applyMermaidThemeTo(renderSource, theme))),
|
|
261
262
|
fullRender ? fullRenderTimeoutMs : renderTimeoutMs,
|
|
262
263
|
)
|
|
263
264
|
if (!mounted || token !== renderToken)
|
|
@@ -315,7 +316,7 @@
|
|
|
315
316
|
await withTimeout(() => Promise.resolve(mermaid.parse(themedSource)), parseTimeoutMs)
|
|
316
317
|
return true
|
|
317
318
|
}
|
|
318
|
-
await withTimeout(() => Promise.resolve(mermaid.render(
|
|
319
|
+
await withTimeout(() => Promise.resolve(mermaid.render(createMermaidRenderId('markstream-svelte-mermaid-parse'), themedSource)), parseTimeoutMs)
|
|
319
320
|
return true
|
|
320
321
|
}
|
|
321
322
|
|
|
@@ -340,12 +340,17 @@
|
|
|
340
340
|
}
|
|
341
341
|
|
|
342
342
|
const requestIdle = typeof window !== 'undefined' ? (window as any).requestIdleCallback as ((callback: (deadline: { timeRemaining?: () => number }) => void, options?: { timeout?: number }) => number) | undefined : undefined
|
|
343
|
-
|
|
343
|
+
// Idle callbacks and animation frames never run in hidden tabs, which
|
|
344
|
+
// would freeze batch rendering until the page becomes visible again. Fall
|
|
345
|
+
// back to a timer so background rendering keeps progressing (the browser
|
|
346
|
+
// clamps hidden-tab timers, trading pace for progress).
|
|
347
|
+
const documentHidden = typeof document !== 'undefined' && document.visibilityState === 'hidden'
|
|
348
|
+
if (requestIdle && !documentHidden) {
|
|
344
349
|
renderBatchIdle = requestIdle(run, { timeout: Math.max(0, Number(renderBatchIdleTimeoutMs) || 120) })
|
|
345
350
|
return
|
|
346
351
|
}
|
|
347
352
|
|
|
348
|
-
if (typeof window !== 'undefined' && typeof window.requestAnimationFrame === 'function') {
|
|
353
|
+
if (typeof window !== 'undefined' && typeof window.requestAnimationFrame === 'function' && !documentHidden) {
|
|
349
354
|
renderBatchFrame = window.requestAnimationFrame(() => {
|
|
350
355
|
renderBatchFrame = null
|
|
351
356
|
if (delay > 0)
|
|
@@ -6,10 +6,11 @@ import { getMermaid } from './optional/mermaid';
|
|
|
6
6
|
import { getStreamDiffsRuntime } from './optional/streamDiffs';
|
|
7
7
|
import { extractRenderedSvg, toSafeSvgMarkup } from './sanitizeSvg';
|
|
8
8
|
import { hideTooltip, showTooltipForAnchor } from './tooltip/singletonTooltip';
|
|
9
|
+
import { createD2RenderSalt } from './utils/d2RenderSalt';
|
|
10
|
+
import { createMermaidRenderId } from './utils/mermaidRenderId';
|
|
9
11
|
import { normalizeKaTeXRenderInput } from './utils/normalizeKaTeXRenderInput';
|
|
10
12
|
import { renderKaTeXWithBackpressure, setKaTeXCache, WORKER_BUSY_CODE } from './workers/katexWorkerClient';
|
|
11
13
|
import { canParseOffthread, findPrefixOffthread } from './workers/mermaidWorkerClient';
|
|
12
|
-
let mermaidRenderId = 0;
|
|
13
14
|
const rootHandles = new WeakMap();
|
|
14
15
|
const DARK_THEME_OVERRIDES = {
|
|
15
16
|
N1: '#E5E7EB',
|
|
@@ -262,7 +263,7 @@ async function renderMermaid(root, cleanupFns, options, isActive) {
|
|
|
262
263
|
sourceToRender = prefix;
|
|
263
264
|
}
|
|
264
265
|
}
|
|
265
|
-
const renderId =
|
|
266
|
+
const renderId = createMermaidRenderId();
|
|
266
267
|
const rendered = await withTimeout(() => Promise.resolve(mermaid.render(renderId, applyMermaidThemeTo(sourceToRender, theme))), options.final === false
|
|
267
268
|
? Number((_d = (_c = options.mermaidProps) === null || _c === void 0 ? void 0 : _c.renderTimeoutMs) !== null && _d !== void 0 ? _d : 2500)
|
|
268
269
|
: Number((_f = (_e = options.mermaidProps) === null || _e === void 0 ? void 0 : _e.fullRenderTimeoutMs) !== null && _f !== void 0 ? _f : 4000));
|
|
@@ -318,7 +319,7 @@ async function canParseMermaidWithFallback(source, theme, mermaid, options) {
|
|
|
318
319
|
await withTimeout(() => Promise.resolve(mermaid.parse(themedSource)), parseTimeout);
|
|
319
320
|
return true;
|
|
320
321
|
}
|
|
321
|
-
const renderId =
|
|
322
|
+
const renderId = createMermaidRenderId('markstream-svelte-mermaid-parse');
|
|
322
323
|
await withTimeout(() => Promise.resolve(mermaid.render(renderId, themedSource)), parseTimeout);
|
|
323
324
|
return true;
|
|
324
325
|
}
|
|
@@ -436,7 +437,7 @@ async function renderInfographic(root, cleanupFns, options, isActive) {
|
|
|
436
437
|
}
|
|
437
438
|
}
|
|
438
439
|
async function renderD2(root, cleanupFns, options, isActive) {
|
|
439
|
-
var _a, _b, _c, _d, _e, _f;
|
|
440
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
440
441
|
const D2Ctor = await getD2();
|
|
441
442
|
if (!D2Ctor || !isActive())
|
|
442
443
|
return;
|
|
@@ -477,6 +478,7 @@ async function renderD2(root, cleanupFns, options, isActive) {
|
|
|
477
478
|
...(baseOverrides || {}),
|
|
478
479
|
};
|
|
479
480
|
}
|
|
481
|
+
renderOptions.salt = (_g = renderOptions.salt) !== null && _g !== void 0 ? _g : createD2RenderSalt();
|
|
480
482
|
const renderResult = await instance.render(diagram, renderOptions);
|
|
481
483
|
if (!isActive())
|
|
482
484
|
return;
|
|
@@ -721,6 +723,12 @@ function normalizeVisibleCodeText(value) {
|
|
|
721
723
|
async function waitForRenderFrame() {
|
|
722
724
|
if (typeof window === 'undefined' || typeof window.requestAnimationFrame !== 'function')
|
|
723
725
|
return;
|
|
726
|
+
// Animation frames never run in hidden tabs; resolve on a timer so block
|
|
727
|
+
// enhancement keeps progressing while the page is in the background.
|
|
728
|
+
if (typeof document !== 'undefined' && document.visibilityState === 'hidden') {
|
|
729
|
+
await new Promise(resolve => setTimeout(resolve, 0));
|
|
730
|
+
return;
|
|
731
|
+
}
|
|
724
732
|
await new Promise(resolve => window.requestAnimationFrame(() => resolve()));
|
|
725
733
|
}
|
|
726
734
|
function decodeDataPayload(value) {
|
package/dist/index.css
CHANGED
|
@@ -1665,9 +1665,11 @@ body > div[id^="dmermaid-"] {
|
|
|
1665
1665
|
background: var(--markstream-code-fallback-bg, var(--code-bg));
|
|
1666
1666
|
}
|
|
1667
1667
|
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1668
|
+
/* Once the enhanced editor owns the grid row, the retired fallback must leave
|
|
1669
|
+
layout entirely: visibility-only hiding keeps the row at the fallback's
|
|
1670
|
+
(uncollapsed) height, so collapsed diffs reserve space they no longer use. */
|
|
1671
|
+
.markstream-svelte .code-editor-fallback-surface.is-retired {
|
|
1672
|
+
display: none;
|
|
1671
1673
|
}
|
|
1672
1674
|
|
|
1673
1675
|
.code-block-body--expanded {
|
package/dist/index.px.css
CHANGED
|
@@ -1665,9 +1665,11 @@ body > div[id^="dmermaid-"] {
|
|
|
1665
1665
|
background: var(--markstream-code-fallback-bg, var(--code-bg));
|
|
1666
1666
|
}
|
|
1667
1667
|
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1668
|
+
/* Once the enhanced editor owns the grid row, the retired fallback must leave
|
|
1669
|
+
layout entirely: visibility-only hiding keeps the row at the fallback's
|
|
1670
|
+
(uncollapsed) height, so collapsed diffs reserve space they no longer use. */
|
|
1671
|
+
.markstream-svelte .code-editor-fallback-surface.is-retired {
|
|
1672
|
+
display: none;
|
|
1671
1673
|
}
|
|
1672
1674
|
|
|
1673
1675
|
.code-block-body--expanded {
|
package/dist/index.tailwind.css
CHANGED
|
@@ -1665,9 +1665,11 @@ body > div[id^="dmermaid-"] {
|
|
|
1665
1665
|
background: var(--markstream-code-fallback-bg, var(--code-bg));
|
|
1666
1666
|
}
|
|
1667
1667
|
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1668
|
+
/* Once the enhanced editor owns the grid row, the retired fallback must leave
|
|
1669
|
+
layout entirely: visibility-only hiding keeps the row at the fallback's
|
|
1670
|
+
(uncollapsed) height, so collapsed diffs reserve space they no longer use. */
|
|
1671
|
+
.markstream-svelte .code-editor-fallback-surface.is-retired {
|
|
1672
|
+
display: none;
|
|
1671
1673
|
}
|
|
1672
1674
|
|
|
1673
1675
|
.code-block-body--expanded {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function createD2RenderSalt(prefix?: string): string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// D2 derives the ids and style-scope classes of its SVG output from a hash of the
|
|
2
|
+
// diagram source, so two identical diagrams would otherwise emit duplicate
|
|
3
|
+
// `id`/`url(#…)` targets and two document-level `.d2-<hash>` style scopes — one
|
|
4
|
+
// of them then wins and the diagrams get each other's colours. D2 exposes
|
|
5
|
+
// `RenderOptions.salt` for exactly this case ("useful when generating multiple
|
|
6
|
+
// identical diagrams to be included in the same HTML doc"). Every render takes a
|
|
7
|
+
// fresh salt from this module-scoped counter, which the block component and
|
|
8
|
+
// `enhanceRenderedHtml` share, so both render paths stay unique on one page.
|
|
9
|
+
let d2RenderSaltSequence = 0;
|
|
10
|
+
export function createD2RenderSalt(prefix = 'markstream-svelte-d2') {
|
|
11
|
+
d2RenderSaltSequence += 1;
|
|
12
|
+
return `${prefix}-${d2RenderSaltSequence}`;
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function findFootnoteElement(source: EventTarget | null | undefined, id: string): Element | null;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Footnote ids are derived from the markdown label (`fnref-<label>` / `fnref--<label>`), so the
|
|
2
|
+
// same id can exist in several renderer trees on one page. Resolve the target inside the tree the
|
|
3
|
+
// clicked element belongs to, and only fall back to the document when that tree has no match.
|
|
4
|
+
const RENDERER_ROOT_SELECTOR = '.markdown-renderer';
|
|
5
|
+
function toIdSelector(id) {
|
|
6
|
+
return `[id="${id.replace(/["\\]/g, '\\$&')}"]`;
|
|
7
|
+
}
|
|
8
|
+
export function findFootnoteElement(source, id) {
|
|
9
|
+
var _a, _b;
|
|
10
|
+
if (typeof document === 'undefined' || typeof Element === 'undefined')
|
|
11
|
+
return null;
|
|
12
|
+
const selector = toIdSelector(id);
|
|
13
|
+
let scope = source instanceof Element ? source.closest(RENDERER_ROOT_SELECTOR) : null;
|
|
14
|
+
while (scope) {
|
|
15
|
+
const found = scope.querySelector(selector);
|
|
16
|
+
if (found)
|
|
17
|
+
return found;
|
|
18
|
+
scope = (_b = (_a = scope.parentElement) === null || _a === void 0 ? void 0 : _a.closest(RENDERER_ROOT_SELECTOR)) !== null && _b !== void 0 ? _b : null;
|
|
19
|
+
}
|
|
20
|
+
return document.querySelector(selector);
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function createMermaidRenderId(prefix?: string): string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Mermaid keys both its temporary render container (`#d<id>`) and the produced
|
|
2
|
+
// `<svg id>` by the id handed to `mermaid.render`, then resolves that id again
|
|
3
|
+
// when it binds interactions. The id therefore has to be unique across every
|
|
4
|
+
// diagram on the page — not just within one block instance: an instance-local
|
|
5
|
+
// counter made two blocks render as `markstream-svelte-mermaid-1`, which left
|
|
6
|
+
// one of the previews blank (issue #775). This module-scoped counter is shared
|
|
7
|
+
// by the block component and `enhanceRenderedHtml`, so both render paths stay
|
|
8
|
+
// collision-free on the same page.
|
|
9
|
+
let mermaidRenderSequence = 0;
|
|
10
|
+
export function createMermaidRenderId(prefix = 'markstream-svelte-mermaid') {
|
|
11
|
+
mermaidRenderSequence += 1;
|
|
12
|
+
return `${prefix}-${mermaidRenderSequence}`;
|
|
13
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "markstream-svelte",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "2.0.
|
|
4
|
+
"version": "2.0.16",
|
|
5
5
|
"description": "Svelte 5 and SvelteKit streaming Markdown renderer for AI chat, LLM token streams, SSE/WebSocket output, incomplete Markdown, Mermaid, KaTeX, stream-diffs powered code blocks, and custom Svelte components.",
|
|
6
6
|
"author": "Simon He",
|
|
7
7
|
"license": "MIT",
|
|
@@ -100,8 +100,8 @@
|
|
|
100
100
|
},
|
|
101
101
|
"dependencies": {
|
|
102
102
|
"@floating-ui/dom": "^1.8.0",
|
|
103
|
-
"markstream-core": "2.0.
|
|
104
|
-
"stream-markdown-parser": "1.2.
|
|
103
|
+
"markstream-core": "2.0.16",
|
|
104
|
+
"stream-markdown-parser": "1.2.18"
|
|
105
105
|
},
|
|
106
106
|
"devDependencies": {
|
|
107
107
|
"@sveltejs/package": "^2.5.8",
|
|
@@ -120,6 +120,7 @@
|
|
|
120
120
|
"dev": "vite dev",
|
|
121
121
|
"preview": "vite preview",
|
|
122
122
|
"typecheck": "svelte-check --tsconfig ./tsconfig.json",
|
|
123
|
+
"test": "vitest run --config vitest.config.ts",
|
|
123
124
|
"check:core-published": "node ../../scripts/check-core-published.mjs --package-json package.json --core-package-json ../markstream-core/package.json",
|
|
124
125
|
"check:workspace-deps-published": "node ../../scripts/check-workspace-deps-published.mjs --package-json package.json",
|
|
125
126
|
"release": "pnpm run check:workspace-deps-published && bumpp --all --commit --no-tag --no-push --execute 'pnpm --workspace-root run docs:llms:generate' && DIST_TAG=\"$(node ../../scripts/dist-tag.mjs)\" && pnpm publish --access public --tag \"${DIST_TAG}\" && node ../../scripts/tag-package.mjs --package-json package.json --push"
|